hibernate/hibernate-orm · critical · TransactionException
JDBC begin transaction failed:
Error message
JDBC begin transaction failed:
What it means
Thrown when Hibernate cannot start a physical JDBC transaction: AbstractLogicalConnectionImplementor.begin() calls Connection.setAutoCommit(false) (unless the provider disables autocommit) and wraps any SQLException in this TransactionException. The message itself is generic; the real cause is always chained as getCause(). The transaction never became ACTIVE, so nothing was begun on the database side.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java:71
getResourceRegistry().releaseResources();
}
// PhysicalJdbcTransaction impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected abstract Connection getConnectionForTransactionManagement();
@Override
public void begin() {
try {
if ( !doConnectionsFromProviderHaveAutoCommitDisabled() ) {
CONNECTION_LOGGER.preparingToBeginViaSetAutoCommitFalse();
getConnectionForTransactionManagement().setAutoCommit( false );
CONNECTION_LOGGER.transactionBegunViaSetAutoCommitFalse();
}
status = TransactionStatus.ACTIVE;
}
catch( SQLException e ) {
throw new TransactionException( "JDBC begin transaction failed: ", e );
}
}
@Override
public void commit() {
if ( isPhysicallyConnected() ) {
commitConnection();
}
else {
errorIfClosed();
status = TransactionStatus.COMMITTED;
}
afterCompletion();
}
private void commitConnection() {
try {
CONNECTION_LOGGER.preparingToCommitViaConnectionCommit();View on GitHub (pinned to fad1729dce)
Solutions
- Inspect the chained SQLException (SQLState + vendor error code) to identify the real failure before changing anything
- Fix pool settings: set maxLifetime below the DB idle timeout and enable checkout validation (isValid / test query)
- If running under JTA, configure hibernate.transaction.coordinator_class=jta so Hibernate does not drive setAutoCommit itself
- If transient (connection class 08xxx), retry the whole unit of work on a fresh Session/EntityManager
Example fix
// before
em.getTransaction().begin(); // TransactionException: JDBC begin transaction failed
// after
try {
em.getTransaction().begin();
} catch (org.hibernate.TransactionException te) {
Throwable root = te.getCause();
while (root.getCause() != null) root = root.getCause();
// root is the SQLException: classify (transient vs fatal) and retry with a new EntityManager if transient
}
// plus pool hygiene: hikari maxLifetime < DB wait_timeout, connection validation enabled Defensive patterns
Strategy: try-catch
Validate before calling
// validate the pooled connection before beginning, on a session you are about to use em.unwrap(org.hibernate.Session.class).doReturningWork(conn -> conn.isValid(1));
Type guard
static boolean isJdbcBeginFailure(Throwable t) {
return t instanceof org.hibernate.TransactionException
&& t.getMessage() != null
&& t.getMessage().startsWith("JDBC begin transaction failed");
} Try / catch
try {
tx.begin();
} catch (org.hibernate.TransactionException e) {
Throwable root = e.getCause();
while (root != null && root.getCause() != null) root = root.getCause();
// root is the SQLException: classify by SQLState (08xxx = connection, transient) and
// either retry with a fresh EntityManager or surface the real cause to ops
} Prevention
- Set pool maxLifetime below the database's idle-connection timeout (e.g. HikariCP maxLifetime < MySQL wait_timeout)
- Enable connection validation on checkout so dead connections never reach begin()
- Never reuse a Session after any exception without closing it first
- Run begin() inside try and guarantee rollback or close in finally
When it happens
Trigger: session.beginTransaction() / EntityTransaction.begin() on a resource-local (JDBC) Hibernate session where setAutoCommit(false) throws: the pool handed out an already-closed or network-dead connection, the DB is restarting/failing over, the driver forbids setAutoCommit (e.g. a connection already enlisted in an XA transaction), or the connection was reclaimed mid-flight.
Common situations: MySQL wait_timeout recycling connections while the pool maxLifetime is larger; DB restart or failover under load; reusing a Session after an earlier exception left its connection broken; accidentally using Hibernate's JDBC transaction coordinator on a JTA/XA-managed connection.
Related errors
- Unable to rollback against JDBC Connection
- Unable to query JDBC Connection for current lock-timeout set
- Exception pulsing TransactionCoordinator
- Unable to commit against JDBC Connection
- User-provided Connection via JdbcConnectionAccessProvidedCon
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/192a6551d662e3db.
Report an issue: GitHub.