During the development of my latest pet project I decided to go head-on with many of the latest Java Enterprise APIs. One of these was the Java Persistence API (JPA), which I had already used in a handful of projects before. On previous projects the persistence requirements were very simple. I could use JPA out-of-the-box with TopLink Essentials which is the standard set-up for a JPA project in NetBeans/GlassFish. However, for this new pet project of mine I was in need of storing large binary objects (BLOBs). I was shocked to discover that TopLink Essentials doesn't support the Fetching configuration for relationships and properties. Instead it will Fetch.EAGER everything in a relationship and property. This made my application crash hard (OutOfMemoryException) when ever I would query for all entities containing the BLOB. So, I set out to replace the persistence provider. First I looked at Hibernate. I used Hibernate before JPA was released and never had much trouble with it. Unfortunately I found that Hibernate also doesn't support the fetching configuration (in JPA mode). That lead me to OpenJPA which really surprised me. It is well documented, clean, easy to use, and support the fetch configuration. I've now replaced the persistence provider on two projects with OpenJPA and the performance has increased significantly. However, here are a few gotchas that you have to look out for:
- Auto-generated identity fields must not have a preset value in your JavaBean (hence, this would give you problems:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id = 0L
Instead you should write
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; - Collections are
Fetch.LAZYby default, so if you got an existing using TopLink Essentials, you have to double check that your relations are not throwingLazyInitializationExceptionupon fetching outside the transation. - Remember to specify the Fetch depth (
openjpa.MaxFetchDepth) inpersistence.xmlfor using theFetch.EAGERconfiguration - TopLink Essentials compiles named queries when your application is deploy on the application server, OpenJPA on the other hand compiles the named queries upon first usage.
- When enabling SQL DDL on OpenJPA it doesn't generate foreign key constraints, unlike TopLink Essentials
That's all for now. I'd love to hear about your experiences with OpenJPA or any other persistence provide you find suitable for your need.