Sleep mode lazy loading for one-time reverse traversal - how does it work?

I had problems today when lazy loading did not work when using the matched collection. I found this wonderful article that seems to fix the problem.

http://justonjava.blogspot.co.uk/2010/09/lazy-one-to-one-and-one-to-many.html

One thing I don't understand is how the workaround using FieldHandled works. Can someone help me figure this out? Below is the code (copied from the example by reference):

@Entity public class Animal implements FieldHandled { private Person owner; private FieldHandler fieldHandler; @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal") @LazyToOne(LazyToOneOption.NO_PROXY) public Person getOwner() { if (fieldHandler != null) { return (Person) fieldHandler.readObject(this, "owner", owner); } return owner; } public void setOwner(Person owner) { if (fieldHandler != null) { this.owner = fieldHandler.writeObject(this, "owner", this.owner, owner); return; } this.owner = owner; } public FieldHandler getFieldHandler() { return fieldHandler; } public void setFieldHandler(FieldHandler fieldHandler) { this.fieldHandler = fieldHandler; } } 

What am I missing? Perhaps I do not know enough about the sleeping life cycle here? I'm glad to investigate, but can anyone give me some pointers.

Thanks in advance.

EDIT

I made a lot of changes, so many of my entities implemented FieldHandled, but then discovered that some of my tests were unsuccessful. I deflated SQL and got some weird things where SQL was executed in different orders if this interface was implemented only with these methods.

  public FieldHandler getFieldHandler() { return fieldHandler; } public void setFieldHandler(FieldHandler fieldHandler) { this.fieldHandler = fieldHandler; } 

This led to the tests failing, because when I argued, the situation was not quite in the correct state. This adds my misunderstanding of this FieldHandler variable.

+7
source share
2 answers

The following code tells Hibernate to use an interception handler instead of a proxy.

 @LazyToOne(LazyToOneOption.NO_PROXY) 

From javadoc:

return the real object loaded when the link was requested (bytecode amplification is required for this parameter, return to PROXY is returned if the class is not extended)

As you can see, using it requires a bytecode tool before using it. A "persistent class is reinforced" after its "bytecode" toolkit ".

The idea is to trick Hibernate that the entity class we want to use has already been instrumentalized

The Instrumentation task is called after compiling the code. The tool object extends FieldHandled . FieldHandled is an interface introduced in an extended class

Hibernate checks the entity at runtime and concludes that the class has been extended, so it uses a real object instead of a proxy and does not load the associated object of the object, as it usually did .

Edit:

Let's take a look under the hood:

Therefore, this required either a code tool (for example, with InstrumentTask ), or implement FieldHandled .


To make a long story short, you can take a look at EntityType#resolveIdentifier(Serializable, SessionImplementor) . This is the reason why the second object does not load, even if it is invalid.

+9
source

The FieldHandled interface FieldHandled been replaced by the PersistentAttributeInterceptable interface in Hibernate 5. You can achieve the same result by implementing this new interface:

 @Entity public class Animal implements PersistentAttributeInterceptable { private Person owner; private PersistentAttributeInterceptor interceptor; @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal") @LazyToOne(LazyToOneOption.NO_PROXY) public Person getOwner() { if (interceptor != null) { return (Person) interceptor.readObject(this, "owner", owner); } return owner; } public void setOwner(Person owner) { if (interceptor != null) { this.owner = interceptor.writeObject(this, "owner", this.owner, owner); return; } this.owner = owner; } @Override public PersistentAttributeInterceptor $$_hibernate_getInterceptor() { return interceptor; } @Override public void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor) { this.interceptor = interceptor; } } 
+4
source

All Articles