JPA Hibernate Alternatives: When JPA & Hibernate Aren't Right for Your Project

Hello, how are you?

Today we will talk about situations in which the use of the JPA/Hibernate is not recommended. Which alternatives do we have outside the JPA world?

What we will talk about:

I have created 4 CRUDs in my github using the frameworks mentioned in this post, you will find the URL at the beginning of each page.

I am not a radical that thinks that JPA is worthless, but I do believe that we need to choose the right framework for the each situation. If you do not know I wrote a JPA book (in Portuguese only) and I do not think that JPA is the silver bullet that will solve all the problems.

I hope you like the post. [=

JPA/Hibernate Problems

There are times that JPA can do more harm than good. Below you will see the JPA/Hibernate problems and in the next page you will see some solutions to these problems:

After reading all the problems above you might be thinking: “Is JPA good in doing anything?”. JPA has a lot of advantages that will not be detailed here because this is not the post theme, JPA is a tool that is indicated for a lot of situations. Some of the JPA advantages are: database portability, save a lot of the development time, make easier to create queries, cache optimization, a huge community support, etc.

In the next page we will see some solutions for the problems detailed above, the solutions could help you to avoid a huge persistence framework refactoring. We will see some tips to fix or to workaround the problems described here.

Solutions to Some of the JPA/Hibernate problems

We need to be careful if we are thinking about removing the JPA of our projects.

I am not of the developer type that thinks that we should remove a entire framework before trying to find a solution to the problems. Some times it is better to choose a less intrusive approach.

Composite Key

Unfortunately there is not a good solution to this problem. If possible, avoid the creation of tables with composite key if it is not required by the business rules. I have seen developers using composite keys when a simple key could be applied, the composite key complexity was added to the project unnecessarily.

Legacy Databases

The newest JPA version (2.1) has support to StoredProcedures and Functions, with this new resource will be easier to communicate with the database. If a JPA version upgrade is not possible I think that JPA is not the best solution to you.

You could use some of the vendor resources, e.g. Hibernate, but you will lose database and implementations portability.

Artifact Size

An easy solution to this problem would be to change the JPA implementation. Instead of using the Hibernate implementation you could use the Eclipsellink, OpenJPA or the Batoo. A problem might appear if the project is using Hibernate annotation/resources; the implementation change will require some code refactoring.

Generated SQL and Complexes Query

The solution to these problems would be a resource named NativeQuery. With this resource you could have a simplified query or optimized SQL, but you will sacrifice the database portability.

You could put your queries in a file, something like SEARCH_STUDENTS_ORACLE or SEARCH_STUDENTS_MYSQL, and in production environment the correct file would be accessed. The problem of this approach is that the same query must be written for every database. If we need to edit the SEARCH_STUDENTS query, it would be required to edit the oracle and mysql files.

If your project is has only one database vendor the NativeQuery resource will not be a problem.

The advantage of this hybrid approach (JPQL and NativeQuery in the same project) is the possibility of using the others JPA advantages.

Slow Processing and Huge Memory Size

This problem can be solved with optimized queries (with NativeQuery), query pagination and small transactions.

Avoid using EJB with PersistenceContext Extended, this kind of context will consume more memory and processing of the server.

There is also the possibility of getting an entity from database as a “read only” entity, e.g.: entity that will only be used in a report. To recover an entity in a “read only” state is not needed to open a transaction, take a look at the code below:

String query = "select uai from Student uai";
EntityManager entityManager = entityManagerFactory.createEntityManager();
TypedQuery<Student> typedQuery = entityManager.createQuery(query, Student.class);
List<Student> resultList = typedQuery.getResultList();

Notice that in the code above there is no opened transaction, all the returned entities will be detached (non monitored by the JPA). If you are using EJB mark your transaction as NOT_SUPPORTED or you could use @Transactional(readOnly=true).

Complexity

I would say that there is only one solution to this problem: to study. It will be necessary to read books, blogs, magazines or any other trustful source of JPA material. More study is equals to less doubts in JPA.

I am not a developer that believes that JPA it is the only and the best solution to every problem, but there are moments that JPA is not the best to tool to use.

You must be careful when deciding about a persistence framework change, usually a lot of classes are affected and a huge refactoring is needed. Several bugs may be caused by this refactoring. It is needed to talk with the project mangers about this refactoring and list all the positive and negative effects.

In the next four pages we will see 4 persistence frameworks that can be used in our projects, but before we see the frameworks I will show how that I choose each framework.

Criteria for Choosing the frameworks Described Here

Maybe you will think: “why the framework X is not here?”. Below I will list the criteria applied for choosing the framework displayed here:

The frameworks that will be displayed in here has good methods and are easy to use.

To make a real CRUD scenario we have a persistence model like below:

With this characteristics in a class we will see some problems and how the framework solve it.

Spring JDBC Template

One of the most famous frameworks that we can find to access the database data is the Spring JDBC Template.

The code of this project can be found in here: https://github.com/uaihebert/SpringJdbcTemplateCrud

The Sprint JDBC Template uses natives queries like below:

Spring01

As it is possible to see in the image above the query has a database syntax (I will be using MySQL). When we use a native SQL query it is possible to use all the database resources in an easy way.

We need an instance of the object JDBC Template (used to execute the queries), and to create the JDBC Template object we need to set up a datasource:

Spring03

We can get the datasource now (thanks to the Spring injection) and create our JDBCTemplate:

Spring04

PS.: All the XML code above and the JDBCTemplate instantiation could be replace by Spring injection and with a code bootstrap, just do a little research about the Spring features.

One thing that I did not liked is the INSERT statement with ID recover, it is very verbose:

Spring05

With the KeyHolder class we can recover the generated ID in the database, unfortunately we need a huge code to do it.

The other CRUD functions are easier to use, like below:

Spring06

Notice that to execute a SQL query it is very simple and results in a populated object, thanks to the RowMapper. The RowMapper is the engine that the JDBC Template uses to make easier to populate a class with data from the database. Take a look at the RowMapper code below:

Spring07

The best news about the RowMapper is that it can be used in any query of the project. The developer that is responsible to write the logic that will populate the class data.

To finish this page, take a look below in the database DELETE and the database UPDATE statement:

Spring09

Spring08

About the Spring JDBC Template we can say:

To those that does not know the Spring has several modules and in your project it is possible to use only the JDBC Template module. You could keep all the other modules/frameworks of your project and add only the necessary to run the JDBC Template.

MyBatis

MyBatis (created with the name iBatis) is a very good framework that is used by a lot of developers. Has a lot of functionalities, but we will only see a few in this post.

The code of this page can be found in here: https://github.com/uaihebert/MyBatisCrud

To run your project with MyBatis you will need to instantiate a Session Factory. It is very easy and the documentation says that this factory can be static:

MyBatis01

When you run a project with MyBatis you just need to instantiate the Factory one time, that is why it is in a static code. The configuration XML (mybatis.xml) it is very simple and its code can be found below:

MyBatis02

The Mapper (an attribute inside the XML above) will hold information about the project queries and how to translate the database result into Java objects. It is possible to create a Mapper in XML or Interface. Let us see below the Mapper found in the file crud_query.xml:

MyBatis03

Notice that the file is easy to understand. The first configuration found is a ResultMap that indicates the query result type, and a result class was configured “uai.model.Customer”. In the class we have a attribute with a different name of the database table column, so we need to add a configuration to the ResultMap.

All queries need a ID that will be used by MyBatis session. In the beginning of the file it is possible to see a namespace declared that works as a Java package, this package will wrap all the queries and the ResultMaps found in the XML file.

We could also use a Interface+Annotation instead of the XML. The Mapper found in the crud_query.xml file could be translated in to a Interface like:

MyBatis04

Only the Read methods were written in the Interface to make the code smaller, but all the CRUD methods could be written in the Interface.

Let us see first how to execute a query found in the XML file:

MyBatis05

The parsing of the object is automatically and the method is easy to read. To run the query all that is needed is to use the combination “namespace + query id” that we saw in the crud_query.xml code above.

If the developer wants to use the Interface approach he could do like below:

MyBatis06

With the interface query mode we have a clean code and the developer will not need to instantiate the Interface, the session class of the MyBatis will do the work.

If you want to update, delete or insert a record in the database the code is very easy:

MyBatis07

MyBatis08

MyBatis09

About MyBatis we could say:

Sormula

Sormula is a ORM OpenSource framework, very similar to the JPA/Hibernate.

The code of the project in this page can be found in here: https://github.com/uaihebert/SormulaCrud

Sormula has a class named Database that works like the JPA EntityManagerFactory, the Database class will be like a bridge between the database and your model classes. To execute the SQL actions we will use the Table class that works like the JPA EntityManager, but the Table class is typed.

To run Sormula in a code you will need to create a Database instance:

Sor01

To create a Database instance all that we need is a Java Connection.

To read data from the database is very easy, like below:

Sor02

You only need to create a Database instance and a Table instance to execute all kind of SQL actions.

How can we map a class attribute name different from the database table column name? Take a look below:

Sor03

We can use annotations to do the database mapping in our classes, very close to the JPA style.

To update, delete or create data in the database you can do like below:

Sor04

Sor05

Sor06

About Sormula we can say that:

sql2o

This framework works with native SQL and makes easier to transform database data into Java objects.

The code of the project in this page can be found in here: https://github.com/uaihebert/sql2oCrud

sql2o has a Connection class that is very easy to create:

SQ01

Notice that we have a static Sql2o object that will work like a Connection factory.

To read the database data we would do something like:

SQ02

Notice that we have a Native SQL written, but we have named parameters. We are not using positional parameters like ‘?1′ but we gave a name to the parameter like ‘:id’. We can say that named parameters has the advantage that we will not get lost in a query with several parameters; when we forget to pass some parameter the error message will tell us the parameter name that is missing.

We can inform in the query the name of the column with a different name, there is no need to create a Mapper/RowMapper. With the return type defined in the query we will not need to instantiate manually the object, sql2o will do it for us.

If you want to update, delete or insert data in the database you can do like below:

SQ03

SQ04

SQ05

It is a “very easy to use” framework.

About the sql2o we can say that:

Take a look at: jOOQ and Avaje

jOOQ

jOOQ it is a framework indicated by a lot of people, the users of this frameworks praise it in a lot of sites/forums.

Unfortunately the jOOQ did not work in my PC because my database was too old, and I could not download other database when writing this post (I was in an airplane).

I noticed that to use the jOOQ you will need to generated several jOOQ classes based in your model. jOOQ has a good documentation in the site and it details how to generate those classes.

jOOQ is free to those that uses a free database like: MySQL, Postgre, etc. The paid jOOQ version is needed to those that uses paid databases like: Oracle, SQL Server, etc.

www.jooq.org/

Avaje

Is a framework quoted in several blogs/forums. It works with the ORM concept and it is easy to execute database CRUD actions.

Problems that I found:

www.avaje.org

Is a Raw JDBC Approach Worth It?

The advantages of JDBC are:

The disadvantages are:

I can see only one factor that would make me choose a raw JDBC approach almost instantly:

I do like JDBC a lot, I have worked and I still working with it. I just ask you to not think that JDBC is the silver bullet for every problem.

If you know any other advantage/disadvantage that is not listed here, just tell me and I will add here with the credits going to you. [=

How Can I Choose the Right Framework?

We must be careful if you want to change JPA for other project or if you are just looking for other persistence framework. If the solutions in page 3 are not solving your problems the best solution is to change the persistence framework.

What should you considerate before changing the persistence framework?

Final Thoughts

I will say it again: I do not think that JPA could/should be applied to every situation in every project in the world; I do no think that that JPA is useless just because it has disadvantages just like any other framework.

I do not want you to be offended if your framework was not listed here, maybe the research words that I used to find persistence frameworks did not lead me to your framework.

I hope that this post might help you.

If your have any double/question just post it. [=

See you soon! \o_


 

 

 

 

Top