My question is rather Matrix-esque in that I've already written the code and it works but I'm trying to understand it.
Anyways, I'm using Hibernate and I'm using JPA calls and JPA annotations for the class that is mapped to a table. Again everything works fine. I have a simple CRUD sample application where objects are added, edited, deleted, and listed. I have the following variable in the service class:
My addCustomer method is:
My question is:
1) Am I doing this in the most efficient manner? I seem to remember reading somewhere (can't remember where) that there was no penalty for continuing recreate a factory and the entity manager but my intuition is suggesting otherwise. Any feedback most welcome.
posted 9 years ago
I found the answer to my own question so I figured I'd post it in case anyone else winds up with the same question. First, a great link from the Apache Software Foundation describes the differences between each of the classes and their purpose:
So, I created a simple servlet that did the following within its doGet:
The above code utilized a static EntityManagerFactory declared within the servlet. The average time was about 0.15 ms and so the performance was quite good; I had seen a post somewhere from 2007 where someone claimed that TopLink's ORM was 140+ ms per operation - but don't know if that was correct or not.
Next I did the following:
The average, which I was only able to run twice, gave an average time of about 130 ms. Quite the difference! However, and this has more of an implication than the performance, but attempting to call this servlet (i.e. reload page) more than twice caused an exception stack trace with Hibernate declaring that MySQL couldn't honor the request due to "too many connections". I attempted to reconfigure Hibernate to allow more connections (and also MySQL) but the times did not change.
More explanation about why this performance difference exists comes from the Hibernate documentation for EntityManager:
When Persistence.createEntityManagerFactory() is called, the persistence implementation will search your classpath for any META-INF/persistence.xml files using the ClassLoader.getResource("META-INF/persistence.xml") method. Actually the Persistence class will look at all the Persistence Providers available in the classpath and ask each of them if they are responsible for the creation of the entity manager factory manager1. Each provider, from this list of resources, it will try to find an entity manager that matches the name you specify in the command line with what is specified in the persistence.xml file (of course the provider element must match the current persistent provider). If no persistence.xml with the correct name are found or if the expected persistence provider is not found, a PersistenceException is raised.
An entity manager factory is typically create at application initialization time and closed at application end. It's creation is an expensive process. For those who are familiar with Hibernate, an entity manager factory is very much like a session factory. Actually, an entity manager factory is a wrapper on top of a session factory. Calls to the EntityManagerFactory are thread safe.
So it's safe to set up an entity manager factory as a static variable because it is thread safe - but also because it is an expensive operation.
A EntityManagerFactory is an expensive-to-create, threadsafe object intended to be shared by all application threads. It is created once, usually on application startup.
So, at this point there should be no question whether or not EntityManagerFactory should be a static, even final, variable in a class.
Anyway, I figured I'd share this in case anyone else fairly new to application managed entity managers comes across this sort of an issue. I had been using JBoss Seam and so Seam had been managing the entity manager for me via DI and I therefore did not have to know the intrinsic behavior of entity managers and what's involved.
Btw: if anyone sees anything to add or correct (if I'm incorrect about any of this), please post.