There are 19 methods in our DAO layer, each is some variation of this:
public TicketProp saveTicketProp(TicketProp prop) {
EntityManager em = this.emf.createEntityManager();
try {
em.getTransaction().begin();
prop = (TicketProp) em.merge(prop);
em.getTransaction().commit();
return prop;
} finally {
em.close();
}
}
Meaning: In each method we handle our own transaction and close it in a finally block. We're testing a Jersey app, so our JUnit tests extend JerseyTest. Each test method instantiates a Grizzly container, runs the test, then shuts down the container. EntityManagerFactory is injected by spring. We're using JPA over Hibernate.
I'm monitoring the connections to our MySQL test DB and they're always high. One test alone runs the MySQL "Max_used_connections" variable to 38. For fun, I went and commented out all the em.close() calls, and the test still uses 38 connections.
I'm using Hibernate's built-in connection pooling (not for prod use, I know). I still expected some sort of intelligent pooling.
Am I handling the EntityManager wrong? How else can I close connections?
You should close
the EntityManagerFactory
at the end of your test. From the javadoc of EntityManagerFactory#close()
:
void javax.persistence.EntityManagerFactory.close()
Close the factory, releasing any resources that it holds. After a factory instance has been closed, all methods invoked on it will throw the
IllegalStateException
, except forisOpen
, which will return false. Once anEntityManagerFactory
has been closed, all its entity managers are considered to be in the closed state.
As a side note, you should actually rollback the transaction before closing the EM in the finally
clause:
public TicketProp saveTicketProp(TicketProp prop) {
EntityManager em = this.emf.createEntityManager();
try {
em.getTransaction().begin();
prop = (TicketProp) em.merge(prop);
em.getTransaction().commit();
return prop;
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
}
Why do you think that EntityManager.close()
always physically closes underlying connection? It's up to connection pool (you probably need to configure it and set the maximum number of simultaneously open connections).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With