Solve EntityManager Problem in JPA and Hibernate

JPAHibernate

Problem

I always asked myself that what is a the best way when you are not using JTA in your project but need a consistent JDBC connection to database. This means That:

1- I have a web application which is running in a standard application server, suppose Tomcat.

2- I want to use database connection when ever is needed.

3- I may use ORM frameworks such as Hibernate

 What I did

I used a singleton object for EntityManager object which every time would be checked if the reference is trusted or not by checking it against null value.

After I think 10 versions of artifacts that I have sent to production users, I got some reports for false data! That means data would be shown to user but somehow 1 at 1000 times one of rows would not show correct data.

What is right to do

The best practice for this problem is using separate EntityManager for every transaction that you need to do. This solution is even  applies to even JTA based transaction. (I know you would face this problem soon if you had this one!)

So for the problem you should:

1- create a WebContextListener to create a EntityManagerFactory object as a static object and use it when ever you need to .

2- create EntityManager object every time you need to begin a transaction or fetch data.

3- be sure to close all the resources and rollback the transactions in case of exception or shutting down the server (by using context listener methods) .

 


@WebListener(value = "emfListener")
public class EMF implements ServletContextListener {
private static javax.persistence.EntityManagerFactory emf;

@Override
public void contextInitialized(ServletContextEvent event) {
emf = Persistence.createEntityManagerFactory("FDS_DATA_UNIT");
}

@Override
public void contextDestroyed(ServletContextEvent event) {
emf.close();
}

public static EntityManager createEntityManager() {
if (emf == null) {
throw new IllegalStateException("Context is not initialized yet.");
}

return emf.createEntityManager();
}

}


public String decryptCardNo(String cardNo) {
Query query = EMF.createEntityManager().createNativeQuery("SELECT

ENCRYPTDECRYPT.DECRYPT('" + cardNo + "')FROM DUAL");
String result = String.valueOf(query.getSingleResult());
return result;
}