| The following used to work with Hibernate 5.0.7 and the lazy attribute loading bytecode enhancement enabled, but it breaks with Hibernate 5.1.0. Maybe this is a regression? I have an @Entity that extends a @MappedSuperclass. The @MappedSuperclass is a generic class with a @Transient property whose type is the generic type argument. The @Entity has a @ManyToOne property whose getter and setter methods wrap the @Transient property. The hibernate-enhance-maven-plugin prints that it has Successfully enhanced class for all my classes. And then, when the SessionFactoryBuilder.build() method is running at application startup, it throws the following exception:
org.hibernate.property.access.spi.PropertyAccessBuildingException: Could not locate field for property [team] on bytecode-enhanced Class [com.example.PersonTeamRelation]
at org.hibernate.property.access.internal.PropertyAccessEnhancedImpl.<init>(PropertyAccessEnhancedImpl.java:48)
at org.hibernate.property.access.internal.PropertyAccessStrategyEnhancedImpl.buildPropertyAccess(PropertyAccessStrategyEnhancedImpl.java:27)
at org.hibernate.mapping.Property.getGetter(Property.java:308)
at org.hibernate.tuple.entity.PojoEntityTuplizer.buildPropertyGetter(PojoEntityTuplizer.java:257)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:145)
at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:60)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(EntityTuplizerFactory.java:88)
at org.hibernate.tuple.entity.EntityTuplizerFactory.constructDefaultTuplizer(EntityTuplizerFactory.java:116)
at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:385)
at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:509)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:124)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:344)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465)
My classes look like this (after stripping down for conciseness):
@Entity
@Table(name = "persons_teams")
public class PersonTeamRelation extends PersonRelation<Team> {
private static final long serialVersionUID = 1L;
private boolean administrator;
@ManyToOne(optional = false)
@JoinColumn(name = "team", nullable = false)
@NotNull
public Team getTeam() {
return getOtherEntity();
}
public void setTeam(final Team team) {
setOtherEntity(team);
}
@Column(name = "administrator", nullable = false)
@NotNull
public boolean isAdministrator() {
return this.administrator;
}
public void setAdministrator(final boolean isAdministrator) {
this.administrator = isAdministrator;
}
}
@MappedSuperclass
public abstract class PersonRelation<OtherType extends Serializable> implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Person person;
private OtherType otherEntity;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false, updatable = false)
public Long getId() {
return this.id;
}
public void setId(final Long id) {
this.id = id;
}
@ManyToOne(optional = false)
@JoinColumn(name = "person", nullable = false)
@NotNull
public Person getPerson() {
return this.person;
}
public void setPerson(final Person person) {
this.person = person;
}
@Transient
protected OtherType getOtherEntity() {
return this.otherEntity;
}
protected void setOtherEntity(final OtherType otherEntity) {
this.otherEntity = otherEntity;
}
}
I am configuring the hibernate-enhance-maven-plugin Maven plugin in the following manner:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>5.1.0.Final</version>
<dependencies>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>enhance</goal>
</goals>
<configuration>
<enableLazyInitialization>true</enableLazyInitialization>
<enableDirtyTracking>false</enableDirtyTracking>
<enableAssociationManagement>false</enableAssociationManagement>
<enableExtendedEnhancement>false</enableExtendedEnhancement>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
If this is not a regression, and the setup described above is not supported anymore, it should be mentioned in the 5.1 Migration Guide. |