The Java ecosystem offers lots of ORM frameworks (with lots of different levels of quality). For my project, I wanted to find an ORM that would allow me to use PostgreSQL's advanced features with the least amount of boilerplate code possible. My project will be written in Spring, so Spring integration is also one of the important points.

To gain knowledge on each framework's capabilities, I've decided to implement a demo application that (hopefully) includes all currently available ORMs. The following features have been tested.

Tested ORMs

Some of the frameworks support the required features by default. For others, I had to write some kind of interlayer code. Obsolete frameworks or frameworks that made it impossible to use any of the features have been excluded from this test.

ActiveJDBC is the implementation of the active record pattern. The library is lightweight and easy to use. Unfortunately, it does not integrate with Spring transaction management, so I had to write some code for it. It's author, Igor Polevoy, reacts really quickly to new requests in GitHub's issue tracker.

Apache Cayenne is an ORM that generates domain objects (DO) from an XML model that can be managed by bundled a GUI application called a modeler. Same as ActiveJDBC, I had to write a custom integration into Spring Transaction Management (STA).

Apache OpenJPA is the JPA implementation made by Apache. Even though Spring provides light support for the integration of OpenJPA, it is harder to integrate it than Hibernate. Due to this, I think it doesn't make too much sense to use OpenJPA in the Spring world. The project uses bytecode enhancement of compiled DO classes.

DataNucleus Access Platform (formerly known as JPOX) is a rich framework that provides implementations of JPA, JDO, and REST APIs. For me, the JPA was the easiest way to implement it. The framework provides some handy mappings, like Java 8 time API mapping. Unfortunately, the mappings can't be used in native query calls, so it is necessary to write an extra set of mappings.

Ebean is flexible and lightweight ORM that is actually used by the Play Framework. Even though the ORM is not shipped with Spring, it was really easy to integrate it. The framework uses bytecode enhancement of DO classes.

EclipseLink is the JPA implementation for Eclipse. It has some support in Spring but, like with OpenJPA, it doesn't make too much sense to use it. To be able to use user-defined types, I had to write some mappers. The framework uses a runtime weaver to enhance DOs.

jOOQ is one of the three frameworks that can be chosen on the Spring Initializr page. This means a good integration with Spring. The ORM generates code not only for DOs but also for user-defined types and stored procedures. It still has some flaws, like problems with combining UDTs with POJOs or DAO insert methods that don't return autogenerated primary key values. On the other hand, Lukas Eder, the author of the framework, is doing a really good job of improving the framework and also propagating it on this site.

MyBatis is the third ORM option available on Spring Initializr page. MyBatis is a mature, lightweight framework with good integration with Spring. Unfortunately, due to its lightweightness, it lacks native support for a lot of PostgreSQL's advanced features, so I had work around that limitation to implement it.

Hibernate is used as the default implementation of JPA in the Spring Data JPA project. Thanks to this, it has perfect integration with Spring. The ORM is quite heavy, and I think it is quite hard to use.



JSON Composite or enum type Array Stored procedures Auditing Pagination Time API STA ActiveJDBC Custom mapper Custom mapper Custom mapper Pure JDBC call Custom code Partial support Custom mapper Custom code Cayenne Custom mapper Custom mapper Custom mapper Partial support Custom code Custom code Custom mapper Custom code OpenJPA Custom mapper Custom mapper Custom mapper Partial support Custom code Custom code Custom mapper Default DataNucleus Custom mapper Custom mapper Default Partial support Custom code Custom code Default Default Ebean Default Custom mapper Default Partial support Default Custom code Default Default EclipseLink Custom mapper Custom mapper Custom mapper Partial support Custom code Custom code Custom mapper Default jOOQ Default Default Default Default Custom code Custom code Custom mapper Default MyBatis Custom mapper Custom mapper Custom mapper Partial support Custom code Custom code Custom mapper Default Hibernate Custom mapper Custom mapper Custom mapper Partial support Default Default Default Default





By custom code, I mean that an ORM allows us to use a feature by providing some kind of low-level API, but a lot of work is still up to the developer. Custom mapper or partial support means that an ORM provides higher-level API. And default is used for features that are supported by ORM natively via a method or use an interface.

Excluded ORMs

The following frameworks have been excluded from the test due to lack of support of one or more of the required features or because of other problems. That isn't to say anything negative about them—they're certainly promising—but they didn't suit my needs for one or more reasons.

Exposed is the ORM for Kotlin implemented by JetBrains. I've tried to use it in Jav,a but it was really hard, almost impossible. For Scala developers, this may be a good option.

Reladomo is an enterprise ORM, but it does not support UDTs or other PostgreSQL advanced features.

Speedment does not support transactions in its current stable version.

These frameworks appear to be no longer developed or maintained:

ActiveJPA seems like it never reached stable release, with the last commits from 2014.

Apache Torque had its last commit in 2013.

Carbonado is an inactive project.

Fjorm's last commit is two years old.

Hydrate's last version is from 2006.

IBM PureQuery's last version is from 2009.

JDO Instruments doesn't even have a working homepage.

ORMLite's last version is from 2013.

QuickDB ORM is available only in Google Archive, with its last commit being from 2010.

Speedo's last commit is from 2005.

TJDO Project's last commit is from 2008.

Conclusion

I've decided to use jOOQ in my home project for its good integration with Spring and generated classes, which leads to less boilerplate code in my project. Of course, it has its own cons, and other developers may find different framework more suitable for their needs.