I have an app running Hibernate 4.2.21 on JBoss AS 7.2
We currently have a few @OneToOne relationships which, due to known limitations of lazy loading, will alway fetch eagerly on the inverse side.
In order to enable Lazy loading for inverse relationships I am trying to enable build-time bytecode instrumentation.
Here's what I've done so far...
1) Activate instrumentation using maven-antrun-plugin (I tried the hibernate-enhance-maven-plugin and couldn't get it working but thats for another question), I now get the following maven output in the build log:
[INFO] --- maven-antrun-plugin:1.7:run (Instrument domain classes) @ MyApp-entities ---
[INFO] Executing tasks
instrument:
[instrument] starting instrumentation
[INFO] Executed tasks
2) Next I annotated all @OneToOne relationships as follows...
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "client", optional=false)
@LazyToOne(LazyToOneOption.NO_PROXY)
public ClientPrefs getClientPrefs() {
return clientPrefs;
}
public void setClientPrefs(ClientPrefs clientPrefs) {
this.clientPrefs = clientPrefs;
}
3) Then I add implement FieldHandled to the @Entity classes along with private field and getter and setter:
private FieldHandler fieldHandler;
success...I am now getting following output in the deployment log:
15:54:09,720 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 56) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Session
15:54:09,730 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 57) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Session
15:54:09,969 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 56) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Client
15:54:09,970 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 57) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Client
15:54:09,999 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 56) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Country
15:54:10,003 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 57) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Country
15:54:10,054 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 56) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Pool
15:54:10,054 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 57) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.Pool
15:54:10,569 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 56) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.User
15:54:10,624 INFO [org.hibernate.tuple.entity.EntityMetamodel] (ServerService Thread Pool -- 57) HHH000157: Lazy property fetching available for: uk.co.myapp.entities.User
The relationships now no longer eagerly load...but they don't lazy load either, they just return null silently.
I have tried removing the FieldHandled interface and FieldHandler field from the Entity as I was not sure if this was necessary, after this I no longer get the 'HHH000157: Lazy property fetching available for:'message at startup and it goes back to eagerly loading by default.
Am I missing something here? The hibernate docs are not explicit on how to actually set this up
EDIT: Added the Ant task config as per comments:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>process-classes</phase>
<id>Instrument domain classes</id>
<configuration>
<target name="instrument">
<taskdef name="instrument"
classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
<classpath>
<path refid="maven.dependency.classpath" />
<path refid="maven.plugin.classpath" />
</classpath>
</taskdef>
<instrument verbose="true">
<fileset dir="${project.build.outputDirectory}">
<include name="MyApp-entities/co/uk/myapp/entities/*.class" />
</fileset>
</instrument>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.21.Final</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.1-GA</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
FieldHandledinterface, if you want to do the instrumentation by hand. In that case you will need to callFieldHandler.readObjectbefore every access to your lazy field to ensure that it is initialized properly. But if you activate instrumentation, you must not implementFieldHandled. It seems that you didn't configure the instrumentation task correctly - please add that snippet of your configuration. Btw. if you are using an IDE it might happen that it overwrites the instrumented classes immediately.