简体   繁体   中英

Hibernate JPA @OneToOne Lazy loading

I am trying to make @OneToOne association LAZY , which is EAGER by default.

I can think of two reasons:
1) Fake @OneToOne as @ManyToOne .
2) Have the foreign key column in owner table and then use fetch type as LAZY .

Can anyone please point out the pros/cons of the above strategies. Also, let me know if there is other better solution available.

More correct and clean solution is option 2 - you do not want to modify your model only to instruct underlying ORM framework how to load your data, unless absolutely necessary. However, there are situations where this does not work out of the box, and you must either tweak JPA to really turn on LAZY behavior, or go with option 1 (however, option 1 should use @OneToMany instead of @ManyToOne ).

I will explain and try to demystify option 2 - ie. LAZY loading of @OneToOne and @ManyToOne , which map reference to a single entity (not a collection). Example:

@Entity public class Main { @OneToOne(fetch = FetchType.LAZY) private Secondary secondary; }

The way, how hibernate does the lazy loading, is that it creates a proxy object with the same methods as class Secondary , but only with @Id field set and all other data fields empty. When you call any method on this object for the first time, data is loaded into a new Secondary object and the method call is forwarded. Difference to EAGER loading is not only that data is loaded later only when needed, but also that there will always be an intermediary object between Main and Secondary entities, even after data is loaded. This can only be done by JPA if a subclass of Secondary can be created (if is not final).

Another way to achieve LAZY loading is to modify the original Secondary class to inject data loading code into each method, so that it does not need to be proxied. In fact, the functionality of a proxy object is merged into the code of original class. This is called weaving (or bytecode instrumentation), and can be done during compilation or even during runtime via a special classloader or attached java agent. When comparing efficiency of execution, following inequality applies: Proxying is slower than Dynamic weaving is slower than static weaving. Therefore waving is sort of optimisation. Though, in real world, you rarely care as the slowdown is insignificant.

Generally, if you inject EntityManager as a Java EE resource, via @PersistenceContext annotation, JPA does all the proxying/weaving for you, therefore LAZY loading always works. However, if you create EntityManager manually, like Persistence.createEntityManagerFactory('unit').createEntityManager() , then you might need to enable weaving.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM