Search in sources :

Example 1 with Interceptor

use of org.hibernate.Interceptor in project spring-framework by spring-projects.

the class HibernateTransactionManager method doBegin.

@Override
@SuppressWarnings("deprecation")
protected void doBegin(Object transaction, TransactionDefinition definition) {
    HibernateTransactionObject txObject = (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.getSessionHolder() == null || 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();
        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();
            Integer 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 (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
                // 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);
        }
        if (!definition.isReadOnly() && !txObject.isNewSession()) {
            // We need AUTO or COMMIT for a non-read-only transaction.
            FlushMode flushMode = SessionFactoryUtils.getFlushMode(session);
            if (FlushMode.MANUAL.equals(flushMode)) {
                session.setFlushMode(FlushMode.AUTO);
                txObject.getSessionHolder().setPreviousFlushMode(flushMode);
            }
        }
        Transaction hibTx;
        // Register transaction timeout.
        int 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(timeout);
            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) {
            Connection con = ((SessionImplementor) session).connection();
            ConnectionHolder conHolder = new ConnectionHolder(con);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                conHolder.setTimeoutInSeconds(timeout);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
            }
            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.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 : CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) Connection(java.sql.Connection) InvalidIsolationLevelException(org.springframework.transaction.InvalidIsolationLevelException) FlushMode(org.hibernate.FlushMode) ConnectionHolder(org.springframework.jdbc.datasource.ConnectionHolder) Transaction(org.hibernate.Transaction) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) Interceptor(org.hibernate.Interceptor) Session(org.hibernate.Session)

Example 2 with Interceptor

use of org.hibernate.Interceptor in project hibernate-orm by hibernate.

the class InterceptorTest method testPrepareStatementFaultIntercept.

public void testPrepareStatementFaultIntercept() {
    final Interceptor interceptor = new EmptyInterceptor() {

        @Override
        public String onPrepareStatement(String sql) {
            return null;
        }
    };
    Session s = openSession(interceptor);
    try {
        Transaction t = s.beginTransaction();
        User u = new User("Kinga", "Mroz");
        s.persist(u);
        t.commit();
    } catch (TransactionException e) {
        assertTrue(e.getCause() instanceof AssertionFailure);
    } finally {
        s.close();
    }
}
Also used : TransactionException(org.hibernate.TransactionException) AssertionFailure(org.hibernate.AssertionFailure) Transaction(org.hibernate.Transaction) EmptyInterceptor(org.hibernate.EmptyInterceptor) Interceptor(org.hibernate.Interceptor) EmptyInterceptor(org.hibernate.EmptyInterceptor) Session(org.hibernate.Session)

Example 3 with Interceptor

use of org.hibernate.Interceptor in project hibernate-orm by hibernate.

the class BatchedManyToManyTest method testLoadingNonInverseSide.

@Test
public void testLoadingNonInverseSide() {
    prepareTestData();
    sessionFactory().getStatistics().clear();
    CollectionStatistics userGroupStats = sessionFactory().getStatistics().getCollectionStatistics(User.class.getName() + ".groups");
    CollectionStatistics groupUserStats = sessionFactory().getStatistics().getCollectionStatistics(Group.class.getName() + ".users");
    Interceptor testingInterceptor = new EmptyInterceptor() {

        @Override
        public String onPrepareStatement(String sql) {
            // ugh, this is the best way I could come up with to assert this.
            // unfortunately, this is highly dependent on the dialect and its
            // outer join fragment.  But at least this wil fail on the majority
            // of dialects...
            Assert.assertFalse("batch load of many-to-many should use inner join", sql.toLowerCase(Locale.ROOT).contains("left outer join"));
            return super.onPrepareStatement(sql);
        }
    };
    Session s = openSession(testingInterceptor);
    s.beginTransaction();
    List users = s.createQuery("from User u").list();
    User user = (User) users.get(0);
    assertTrue(Hibernate.isInitialized(user));
    assertTrue(Hibernate.isInitialized(user.getGroups()));
    user = (User) users.get(1);
    assertTrue(Hibernate.isInitialized(user));
    assertTrue(Hibernate.isInitialized(user.getGroups()));
    // should have been just one fetch (the batch fetch)
    assertEquals(1, userGroupStats.getFetchCount());
    // should have been just one fetch (the batch fetch)
    assertEquals(1, groupUserStats.getFetchCount());
    s.getTransaction().commit();
    s.close();
}
Also used : List(java.util.List) EmptyInterceptor(org.hibernate.EmptyInterceptor) Interceptor(org.hibernate.Interceptor) EmptyInterceptor(org.hibernate.EmptyInterceptor) CollectionStatistics(org.hibernate.stat.CollectionStatistics) Session(org.hibernate.Session) Test(org.junit.Test)

Example 4 with Interceptor

use of org.hibernate.Interceptor in project hibernate-orm by hibernate.

the class InterceptorTest method testPrepareStatementIntercept.

@Test
@TestForIssue(jiraKey = "HHH-6594")
public void testPrepareStatementIntercept() {
    final Queue<String> expectedSQLs = new LinkedList<String>();
    // Transaction 1
    expectedSQLs.add("insert");
    // Transaction 2
    expectedSQLs.add("select");
    expectedSQLs.add("select");
    // Transaction 3
    expectedSQLs.add("select");
    expectedSQLs.add("select");
    expectedSQLs.add("update");
    // Transaction 4
    expectedSQLs.add("select");
    expectedSQLs.add("delete");
    final Interceptor interceptor = new EmptyInterceptor() {

        @Override
        public String onPrepareStatement(String sql) {
            assertNotNull(sql);
            String expectedSql = expectedSQLs.poll().toLowerCase(Locale.ROOT);
            assertTrue("sql:\n " + sql.toLowerCase(Locale.ROOT) + "\n doesn't start with \n" + expectedSql + "\n", sql.toLowerCase(Locale.ROOT).startsWith(expectedSql));
            return sql;
        }
    };
    Session s = openSession(interceptor);
    Transaction t = s.beginTransaction();
    User u = new User("Lukasz", "Antoniak");
    s.persist(u);
    t.commit();
    s.close();
    s = openSession(interceptor);
    t = s.beginTransaction();
    s.get(User.class, "Lukasz");
    s.createQuery("from User u").list();
    t.commit();
    s.close();
    u.setPassword("Kinga");
    s = openSession(interceptor);
    t = s.beginTransaction();
    s.merge(u);
    t.commit();
    s.close();
    s = openSession(interceptor);
    t = s.beginTransaction();
    s.delete(u);
    t.commit();
    s.close();
    assertTrue(expectedSQLs.isEmpty());
}
Also used : Transaction(org.hibernate.Transaction) EmptyInterceptor(org.hibernate.EmptyInterceptor) Interceptor(org.hibernate.Interceptor) EmptyInterceptor(org.hibernate.EmptyInterceptor) LinkedList(java.util.LinkedList) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Aggregations

Interceptor (org.hibernate.Interceptor)4 Session (org.hibernate.Session)4 EmptyInterceptor (org.hibernate.EmptyInterceptor)3 Transaction (org.hibernate.Transaction)3 Test (org.junit.Test)2 Connection (java.sql.Connection)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 AssertionFailure (org.hibernate.AssertionFailure)1 FlushMode (org.hibernate.FlushMode)1 TransactionException (org.hibernate.TransactionException)1 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)1 CollectionStatistics (org.hibernate.stat.CollectionStatistics)1 TestForIssue (org.hibernate.testing.TestForIssue)1 ConnectionHolder (org.springframework.jdbc.datasource.ConnectionHolder)1 CannotCreateTransactionException (org.springframework.transaction.CannotCreateTransactionException)1 IllegalTransactionStateException (org.springframework.transaction.IllegalTransactionStateException)1 InvalidIsolationLevelException (org.springframework.transaction.InvalidIsolationLevelException)1