Richard Bolkey – Blog

Icon

Thoughts of a plain old java developer.

The Trouble with Proxies: Hibernate or DataNucleus

Hibernate and DataNucleus (JDO2) are arguably the two most substantial persistence frameworks in the open source ecosystem.  I have worked with DataNucleus quite a bit on the side, and I am now finding an opportunity to use Hibernate during my day job.

I have now spent enough time using Hibernate to appreciate the approach that DataNucleus takes using bytecode enhancement in comparison to Hibernate’s proxies.  Essentially, I am finding myself having to appease Hibernate’s view of the world in unexpected ways where I would like to leave my code alone. Two problem cases have come up so far that I would not have encountered with DataNucleus: using instanceof with type hierarchies and implementing equals.  In both of these case, bytecode enhancement would leave my Java code to work just as I expected; but instead, I have to deal with an extra layer of indirection where I was expecting to deal directly with my objects.

Type hierarchies and instanceof

Lets say that I have the following type hierarchy:

public interface Transformer { ... }
 
public interface Autobot extends Transformer { ... }
 
public interface Decepticon extends Transformer { ... }

Obviously, there are times that I may be given an instance of type Transformer where I want to distinguish between an Autobot and a Decepticon using instanceof.  However, if I am persisting these instances with Hibernate, and I receive a proxy to the persisted entity, I cannot use instanceof to determine the type of the instance I am dealing with.  In Hibernate, the entity instance could well be an Autobot, but the returned proxy to the entity will implement both the Autobot and the Decepticon types.

In order to determine the instance type I am dealing with, I have to either unwrap the proxy or turn off lazy loading.  Both of these are undesirable solutions.  Unwrapping the proxy adds extra persistence operations outside of the persistence tier of your application, which violates a clean separation of concerns.  And of course, there is a performance hit for turning off lazy loading.  I wouldn’t have to use either of these undesirable solutions with DataNucleus.

Implementing equals

This problem seems well documented within the Hibernate community, but it is still an annoyance and evidence of how Hibernate’s design forces you to alter expected Java constructs to fit Hibernate’s needs.  If you want an equals method to play friendly with Hibernate proxies you need to.

  • Do comparisons on properties instead of fields. If you compare on fields, the proxy may return null, comparing on properties will initialize the proxy and return the expected result.
  • Use instanceof comparison instead of class equality.  The type of the proxy is not equal to the type of the entity, but rather extends the type of the entity.
  • Compare to the interface instead of the implementing class. You need to do this if you are using interface proxies instead.

All of the above break the expected construct of the equals method, and DataNucleus does not force you to make any of these concessions.

Conclusion

Obviously, I’m still expanding my knowledge in the Hibernate way of the world, but from just these two headaches I have had with Hibernate, DataNucleus’ approach of using bytecode enhancement looks much superior to the proxying that Hibernate does.

Share/Bookmark

Category: Programming

Tagged: , , ,

One Response

  1. Chrisco says:

    Amen brother!

    I started off using Hibernate a few years back but I tried to find something better when I discovered the awkwardness of Hibernate due to its “proxy compromise” to avoid byte code enhancement. I stumbled across JPOX (now DataNucleus) and haven’t looked back. Now I can model and code how I want, exactly how I want – as a programmer that’s pretty important to me ;)

    As far as the byte code enhancement goes – the latest ASM enhancer is so efficient now that it takes less than a second to enhance the classes in a mega enterprise application that we work on every day – to be honest I don’t even notice it – it’s a tiny portion of the code, compile, deploy cycle.

Leave a Reply