Search in sources :

Example 1 with CannotCreateTransactionException

use of io.micronaut.transaction.exceptions.CannotCreateTransactionException in project micronaut-data by micronaut-projects.

the class MongoSynchronousTransactionManager method doBegin.

@Override
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
    MongoTransaction mongoTransaction = (MongoTransaction) transaction;
    try {
        mongoTransaction.setName(definition.getName());
        if (!mongoTransaction.hasClientSession()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Acquired ClientSession for Mongo transaction [{}]", mongoTransaction);
            }
            ClientSession clientSession = mongoClient.startSession();
            mongoTransaction.setClientSessionHolder(clientSession, true);
        }
        TransactionOptions.Builder txOptionsBuilder = TransactionOptions.builder();
        Duration timeout = determineTimeout(definition);
        if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
            txOptionsBuilder = txOptionsBuilder.maxCommitTime(timeout.toMillis(), TimeUnit.MILLISECONDS);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Starting Mongo transaction [{}]", transaction);
        }
        mongoTransaction.beginTransaction(txOptionsBuilder.build());
        // Bind the client session holder to the thread.
        if (mongoTransaction.isNewClientSession()) {
            TransactionSynchronizationManager.bindResource(mongoClient, mongoTransaction.getClientSession());
        }
    } catch (Throwable ex) {
        mongoTransaction.close();
        throw new CannotCreateTransactionException("Could not open Mongo client session for transaction", ex);
    }
}
Also used : TransactionOptions(com.mongodb.TransactionOptions) ClientSession(com.mongodb.client.ClientSession) CannotCreateTransactionException(io.micronaut.transaction.exceptions.CannotCreateTransactionException) Duration(java.time.Duration)

Example 2 with CannotCreateTransactionException

use of io.micronaut.transaction.exceptions.CannotCreateTransactionException in project micronaut-data by micronaut-projects.

the class HibernateTransactionManager method doBegin.

@Override
@SuppressWarnings("deprecation")
protected void doBegin(Object transaction, TransactionDefinition definition) {
    HibernateTransactionObject txObject = (HibernateTransactionManager.HibernateTransactionObject) transaction;
    if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
        throw new IllegalTransactionStateException("Pre-bound JDBC Connection found! HibernateTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DataSource, no matter whether Hibernate or JDBC access.");
    }
    Session session = null;
    try {
        if (!txObject.hasSessionHolder() || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
            Interceptor entityInterceptor = getEntityInterceptor();
            Session newSession = (entityInterceptor != null ? getSessionFactory().withOptions().interceptor(entityInterceptor).openSession() : getSessionFactory().openSession());
            if (logger.isDebugEnabled()) {
                logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
            }
            txObject.setSession(newSession);
        }
        session = txObject.getSessionHolder().getSession();
        boolean holdabilityNeeded = this.allowResultAccessAfterCompletion && !txObject.isNewSession();
        boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.Isolation.DEFAULT);
        if (holdabilityNeeded || isolationLevelNeeded || definition.isReadOnly()) {
            if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
                // We're allowed to change the transaction settings of the JDBC Connection.
                if (logger.isDebugEnabled()) {
                    logger.debug("Preparing JDBC Connection of Hibernate Session [" + session + "]");
                }
                Connection con = ((SessionImplementor) session).connection();
                TransactionDefinition.Isolation previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
                txObject.setPreviousIsolationLevel(previousIsolationLevel);
                if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
                    int currentHoldability = con.getHoldability();
                    if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
                        txObject.setPreviousHoldability(currentHoldability);
                        con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
                    }
                }
            } else {
                // Not allowed to change the transaction settings of the JDBC Connection.
                if (isolationLevelNeeded) {
                    // We should set a specific isolation level but are not allowed to...
                    throw new InvalidIsolationLevelException("HibernateTransactionManager is not allowed to support custom isolation levels: " + "make sure that its 'prepareConnection' flag is on (the default) and that the " + "Hibernate connection release mode is set to 'on_close' (the default for JDBC).");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Not preparing JDBC Connection of Hibernate Session [" + session + "]");
                }
            }
        }
        if (definition.isReadOnly() && txObject.isNewSession()) {
            // Just set to MANUAL in case of a new Session for this transaction.
            session.setFlushMode(FlushMode.MANUAL);
            // As of 5.1, we're also setting Hibernate's read-only entity mode by default.
            session.setDefaultReadOnly(true);
        }
        if (!definition.isReadOnly() && !txObject.isNewSession()) {
            // We need AUTO or COMMIT for a non-read-only transaction.
            FlushMode flushMode = session.getHibernateFlushMode();
            if (FlushMode.MANUAL.equals(flushMode)) {
                session.setFlushMode(FlushMode.AUTO);
                txObject.getSessionHolder().setPreviousFlushMode(flushMode);
            }
        }
        Transaction hibTx;
        // Register transaction timeout.
        Duration timeout = determineTimeout(definition);
        if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
            // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
            // Applies to all statements, also to inserts, updates and deletes!
            hibTx = session.getTransaction();
            hibTx.setTimeout(((int) timeout.toMillis() / 1000));
            hibTx.begin();
        } else {
            // Open a plain Hibernate transaction without specified timeout.
            hibTx = session.beginTransaction();
        }
        // Add the Hibernate transaction to the session holder.
        txObject.getSessionHolder().setTransaction(hibTx);
        // Register the Hibernate Session's JDBC Connection for the DataSource, if set.
        if (getDataSource() != null) {
            SessionImplementor sessionImpl = (SessionImplementor) session;
            // The following needs to use a lambda expression instead of a method reference
            // for compatibility with Hibernate ORM <5.2 where connection() is defined on
            // SessionImplementor itself instead of on SharedSessionContractImplementor...
            ConnectionHolder conHolder = new ConnectionHolder(sessionImpl::connection);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                conHolder.setTimeout(timeout);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Exposing Hibernate transaction as JDBC [" + conHolder.getConnectionHandle() + "]");
            }
            TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
            txObject.setConnectionHolder(conHolder);
        }
        // Bind the session holder to the thread.
        if (txObject.isNewSessionHolder()) {
            TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
        }
        txObject.getSessionHolder().setSynchronizedWithTransaction(true);
    } catch (Throwable ex) {
        if (txObject.isNewSession()) {
            try {
                if (session != null && session.getTransaction().getStatus() == TransactionStatus.ACTIVE) {
                    session.getTransaction().rollback();
                }
            } catch (Throwable ex2) {
                logger.debug("Could not rollback Session after failed transaction begin", ex);
            } finally {
                SessionFactoryUtils.closeSession(session);
                txObject.setSessionHolder(null);
            }
        }
        throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
    }
}
Also used : TransactionDefinition(io.micronaut.transaction.TransactionDefinition) CannotCreateTransactionException(io.micronaut.transaction.exceptions.CannotCreateTransactionException) IllegalTransactionStateException(io.micronaut.transaction.exceptions.IllegalTransactionStateException) Connection(java.sql.Connection) Duration(java.time.Duration) TypeHint(io.micronaut.core.annotation.TypeHint) InvalidIsolationLevelException(io.micronaut.transaction.exceptions.InvalidIsolationLevelException) SessionImplementor(org.hibernate.engine.spi.SessionImplementor)

Example 3 with CannotCreateTransactionException

use of io.micronaut.transaction.exceptions.CannotCreateTransactionException in project micronaut-data by micronaut-projects.

the class DataSourceTransactionManager method doBegin.

/**
 * This implementation sets the isolation level but ignores the timeout.
 */
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    Connection con = null;
    try {
        if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            Connection newCon = dataSource.getConnection();
            if (logger.isDebugEnabled()) {
                logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
            }
            txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
        }
        txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
        con = txObject.getConnectionHolder().getConnection();
        TransactionDefinition.Isolation previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
        txObject.setPreviousIsolationLevel(previousIsolationLevel);
        // configured the connection pool to set it already).
        if (con.getAutoCommit()) {
            txObject.setMustRestoreAutoCommit(true);
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            con.setAutoCommit(false);
        }
        prepareTransactionalConnection(con, definition);
        txObject.getConnectionHolder().setTransactionActive(true);
        Duration timeout = determineTimeout(definition);
        if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
            txObject.getConnectionHolder().setTimeout(timeout);
        }
        // Bind the connection holder to the thread.
        if (txObject.isNewConnectionHolder()) {
            TransactionSynchronizationManager.bindResource(dataSource, txObject.getConnectionHolder());
        }
    } catch (Throwable ex) {
        if (txObject.isNewConnectionHolder()) {
            DataSourceUtils.releaseConnection(con, dataSource);
            txObject.setConnectionHolder(null, false);
        }
        throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
    }
}
Also used : TransactionDefinition(io.micronaut.transaction.TransactionDefinition) CannotCreateTransactionException(io.micronaut.transaction.exceptions.CannotCreateTransactionException) Connection(java.sql.Connection) Duration(java.time.Duration)

Aggregations

CannotCreateTransactionException (io.micronaut.transaction.exceptions.CannotCreateTransactionException)3 Duration (java.time.Duration)3 TransactionDefinition (io.micronaut.transaction.TransactionDefinition)2 Connection (java.sql.Connection)2 TransactionOptions (com.mongodb.TransactionOptions)1 ClientSession (com.mongodb.client.ClientSession)1 TypeHint (io.micronaut.core.annotation.TypeHint)1 IllegalTransactionStateException (io.micronaut.transaction.exceptions.IllegalTransactionStateException)1 InvalidIsolationLevelException (io.micronaut.transaction.exceptions.InvalidIsolationLevelException)1 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)1