SessionImpl.close() doesn't close db connections after an exception occurs in java.sql.Connection.rollback(). The db connection remains active in the connection pool and is never released. An exception can occur in Connection.rollback(), for example, when the db connection is lost.
{code} EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin();
JdbcCoordinator connector = ((SessionImpl)entityManager).getJdbcCoordinator(); LogicalConnection logicalConnection = connector.getLogicalConnection();
CustomJdbcConnection // Grabs a new connection = (CustomJdbcConnection)((SessionImpl)entityManager).connection(); object and marks as ACTIVE connection.setThrowErrorOnNextRollback(true); try { assertThrows(() -> entityManager.getTransaction(). // Assume rollback throws an exception ( for example the underlying db connection is lost ) , TransactionException.class); try { entityManager.getTransaction().rollback(); } catch (PersistenceException s) { // } finally { entityManager.close(); } // This should release the connection object back to the pool, but does not entityManager.close(); {code}
Example included, the example uses a subclassed h2 database connection and simulates an exception when calling transaction.rollback().
I understand normally db connection errors are a larger problem that should be addressed outside of hibernate, but in the pathological case where db connections drop it could cause a knock on effect to use up all connections in the db pool. Note that a connection error when issuing a normal query will get converted into a rollback. |
|