7

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?

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
whereismydipp
  • 556
  • 1
  • 8
  • 23
  • 1
    Yes. When the wheel is retrieved I get back a proper object from the database. In the next step I do a wheel.getCar();. In eclipselink the car gets loaded instantly(a query is executed) and I get the a real Car object. In hibernate it seems that I only get back a proxy object(even though a query is executed as I can see in the logger). The question is how to get back the real object after without making the realtionship eager or execute a fetch in the first place. Hope this helps. – whereismydipp Feb 16 '15 at 09:33
  • Because I need the real car object instead of a proxy. I checked the object in the debugger...its definitely a proxy :). – whereismydipp Feb 16 '15 at 09:48
  • Why do you need the real object? What do you want to do that requires the object and not the proxy? – rghome Feb 16 '15 at 09:50
  • Lets assume the car has a name and I want to achieve to get the real name of the car. With the proxy I would get null. – whereismydipp Feb 16 '15 at 09:54
  • I don't think it should return null, but maybe I am missing something.See this post: [link](http://stackoverflow.com/questions/8945365/jpa-hibernate-proxy-not-fetching-real-object-data-sets-all-properties-to-null) and this one: [link](http://stackoverflow.com/questions/27152357/id-getter-returns-null-in-hibernate-proxy-when-the-entity-implements-an-interfac) – rghome Feb 16 '15 at 10:09
  • That was is :). Final (ly) :). Make an answer and u get the bounty. cheers – whereismydipp Feb 16 '15 at 14:54

2 Answers2

6

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.

rghome
  • 8,529
  • 8
  • 43
  • 62
5

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.

Sevle
  • 3,109
  • 2
  • 19
  • 31
Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911