Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load the actual Hibernate entity association and not the LAZY proxy

I'm coming from eclipselink and try to work myself through Hibernate.

Lets assume we have a class Car and a class Wheel. The Car class has n wheels. Both entities are connected with a bidirectional association. More importantly on the Wheel side I have a Car reference:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "car_id")
private Car car;

plus a getter.

Now I want to fetch a wheel using its id. From my EntityManager (not a hibernate Session). I initialize the EntityManager like this:

EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = emf.createEntityManager();

The next step is to fetch a wheel like this:

Wheel wheel = em.find(Wheel.class, 1);

The wheel return the wanted class and its fine. Now I want to know which car is the parent of the wheel with something like:

Car car = wheel.getCar();

With eclipselink, the actual car would have been loaded. With hibernate a proxy class is loaded instead.

The only solution I worked out so far is to set the FetchType.EAGER or directly fetch join the relationship. What I realized is that the SQL statement in Hibernate is still executed, but no real object delivered. Also after

Hibernate.initalize(car)

I cannot retrieve the car entity.

Is there any way to get the expected object back without forming a query or an eager fetch?

like image 411
whereismydipp Avatar asked Feb 13 '15 09:02

whereismydipp


People also ask

What is Hibernate proxy and how it helps in lazy loading?

By definition, a proxy is “a function authorized to act as the deputy or substitute for another”. This applies to Hibernate when we call Session. load() to create what is called an uninitialized proxy of our desired entity class. This subclass will be the one to be returned instead of querying the database directly.

How do you load a lazy object in Hibernate?

To enable lazy loading explicitly you must use “fetch = FetchType. LAZY” on an association that you want to lazy load when you are using hibernate annotations. @OneToMany( mappedBy = "category", fetch = FetchType.

How does lazy loading works in Hibernate How will load a lazily loaded items in Hibernate to avoid lazy load exception?

Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes. Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity's class.

What is the difference between lazy and eager loading in Hibernate?

These data loading strategies we used when one entity class is having references to other Entities like Employee and Phone (phone in the employee). Lazy Loading − Associated data loads only when we explicitly call getter or size method. Use Lazy Loading when you are using one-to-many collections.


2 Answers

You probably don't need to worry about the proxy. The proxy should return all of the properties in the same way that the normal object will.

If the proxy object is not working (it is returning null values), it might be that some of your fields or setters or getters are set to final. Check that out first.

like image 92
rghome Avatar answered Sep 19 '22 04:09

rghome


You need to use the Hibernate specific LazyToOneOption.NO_PROXY annotation:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "car_id")
@LazyToOne(LazyToOneOption.NO_PROXY)
private Car car;

This will instruct Hibernate to load the actual object, instead of giving you a Proxy:

Lazy, give back the real object loaded when a reference is requested (Bytecode enhancement is mandatory for this option, fall back to PROXY if the class is not enhanced) This option should be avoided unless you can't afford the use of proxies

But you'll have to use Bytecode instrumentation to activate this option.

like image 27
Vlad Mihalcea Avatar answered Sep 21 '22 04:09

Vlad Mihalcea