Wednesday, October 03, 2007

Hibernate proxy classes and reflection

I have been struggling the last few days with a small tool to export and import data from a system using Hibernate Object Relational mapping. To make it fairly general, and avoid having to change it when attributes are added to the data model we based it on Java reflection. Fairly straightforward, create an XML file with classnames as tagnames and fields as attributes.

The first problem was object relations. My initial plan was to simply follow them, but sinces they are all bi-directional this would mean looping forever. So we had to add a setup where you tell the tool which object relations should be included.

The next problem was worse. It seems that Hibernate somtimes does not create the right objects when loading objects from the database. Instead so called 'proxy classes' are created. This means that reflection does not work as expected... You cannot use Field to acces the fields, instead you have to use the getter methods. OK, not to complicated, once you know. Unfortunately we had one attribute which did not follow naming standards, so we needed a small hack to make this work. What I would have liked is a way to get the real class and skip the proxy. But i guess you can't get everything.


Erick said...

I read your post on reflection and Hibernate proxies while searching for my own solution, and figured out something that works pretty well.

if (obj instanceof HibernateProxy) {
obj = ((HibernateProxy)obj).getHibernateLazyInitializer().getImplementation();

This creates and initializes (i.e. loads the data if needed or hits the L2 cache) the proxy object into the proper underlying class. If you want to avoid lazy loading, you can check the isUninitialized() flag on the LazyInitializer instance and skip those entries.

Jeremy Martin said...

You sir, should have a statue made in your honor. I'd be to embarrassed to admit to the kind of work around I was coming up with. This solution is a life saver.

mine pekparlak said...

Thanks very much for your idea,
I was trying to write a Dto Entity converter for blazeds and stucked with proxy object, until now.

Onur Atamer

Niv said...

Thanks saver indeed. I had a situation where I needed to compare an object with a collection. Since the classes were of type proxy it returned false. Plus using the isUninitialized( was required in my case.