Java tutorial
/* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.orm.hibernate4; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Savepoint; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.sql.DataSource; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.UserTransaction; import org.hibernate.FlushMode; import org.hibernate.Interceptor; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionBuilder; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.HSQLDialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; import org.hibernate.exception.ConstraintViolationException; import org.junit.After; import org.junit.Test; import org.mockito.InOrder; import org.springframework.beans.factory.BeanFactory; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.jdbc.datasource.ConnectionHolder; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; import org.springframework.transaction.CannotCreateTransactionException; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.UnexpectedRollbackException; import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionTemplate; import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; /** * @author Juergen Hoeller * @since 3.2 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class HibernateTransactionManagerTests { @After public void tearDown() { assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty()); assertFalse(TransactionSynchronizationManager.isSynchronizationActive()); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); } @Test public void testTransactionCommit() throws Exception { final DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); final ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); Query query = mock(Query.class); final List list = new ArrayList(); list.add("test"); given(con.getTransactionIsolation()).willReturn(Connection.TRANSACTION_READ_COMMITTED); given(sf.openSession()).willReturn(session); given(session.getTransaction()).willReturn(tx); given(session.connection()).willReturn(con); given(session.isOpen()).willReturn(true); given(session.createQuery("some query string")).willReturn(query); given(query.list()).willReturn(list); given(session.isConnected()).willReturn(true); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { @Override protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { return sf; } }; lsfb.afterPropertiesSet(); final SessionFactory sfProxy = lsfb.getObject(); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sfProxy); tm.setDataSource(ds); TransactionTemplate tt = new TransactionTemplate(tm); tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); tt.setTimeout(10); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); Object result = tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sfProxy)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sfProxy)) .getSession(); return session.createQuery("some query string").list(); } }); assertTrue("Correct result list", result == list); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(con).setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); verify(con).setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); verify(tx).setTimeout(10); verify(tx).begin(); verify(tx).commit(); verify(session).close(); } @Test public void testTransactionRollback() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); PlatformTransactionManager tm = new HibernateTransactionManager(sf); TransactionTemplate tt = new TransactionTemplate(tm); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); try { tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); throw new RuntimeException("application exception"); } }); fail("Should have thrown RuntimeException"); } catch (RuntimeException ex) { // expected } assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(session).close(); verify(tx).rollback(); } @Test public void testTransactionRollbackOnly() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.AUTO); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); PlatformTransactionManager tm = new HibernateTransactionManager(sf); TransactionTemplate tt = new TransactionTemplate(tm); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); session.flush(); status.setRollbackOnly(); return null; } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); verify(session).flush(); verify(session).close(); verify(tx).rollback(); } @Test public void testParticipatingTransactionWithCommit() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); final ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.AUTO); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { @Override protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { return sf; } }; lsfb.afterPropertiesSet(); final SessionFactory sfProxy = lsfb.getObject(); PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy); final TransactionTemplate tt = new TransactionTemplate(tm); final List l = new ArrayList(); l.add("test"); Object result = tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { return tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); session.flush(); return l; } }); } }); assertTrue("Correct result list", result == l); verify(session).flush(); verify(session).close(); verify(tx).commit(); } @Test public void testParticipatingTransactionWithRollback() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.AUTO); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); PlatformTransactionManager tm = new HibernateTransactionManager(sf); final TransactionTemplate tt = new TransactionTemplate(tm); try { tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { return tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { throw new RuntimeException("application exception"); } }); } }); fail("Should have thrown RuntimeException"); } catch (RuntimeException ex) { // expected } verify(session).close(); verify(tx).rollback(); } @Test public void testParticipatingTransactionWithRollbackOnly() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); PlatformTransactionManager tm = new HibernateTransactionManager(sf); final TransactionTemplate tt = new TransactionTemplate(tm); final List l = new ArrayList(); l.add("test"); try { tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { return tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { status.setRollbackOnly(); return null; } }); } }); fail("Should have thrown UnexpectedRollbackException"); } catch (UnexpectedRollbackException ex) { // expected } verify(session).close(); verify(tx).rollback(); } @Test public void testParticipatingTransactionWithRequiresNew() throws Exception { final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session1 = mock(ImplementingSession.class); ImplementingSession session2 = mock(ImplementingSession.class); Connection con = mock(Connection.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session1, session2); given(session1.beginTransaction()).willReturn(tx); given(session1.isOpen()).willReturn(true); given(session2.beginTransaction()).willReturn(tx); given(session2.isOpen()).willReturn(true); given(session2.getFlushMode()).willReturn(FlushMode.AUTO); given(session1.isConnected()).willReturn(true); given(session1.connection()).willReturn(con); given(session2.isConnected()).willReturn(true); given(session2.connection()).willReturn(con); PlatformTransactionManager tm = new HibernateTransactionManager(sf); final TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { final SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Has thread session", holder != null); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); assertTrue("Not enclosing session", session != holder.getSession()); session.flush(); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); return null; } }); assertTrue("Same thread session as before", holder.getSession() == ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession()); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); return null; } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); verify(session2).flush(); verify(session1).close(); verify(session2).close(); verify(tx, times(2)).commit(); } @Test public void testParticipatingTransactionWithNotSupported() throws Exception { final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Connection con = mock(Connection.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.getSessionFactory()).willReturn(sf); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.AUTO); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); HibernateTransactionManager tm = new HibernateTransactionManager(sf); final TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Has thread session", holder != null); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); return null; } }); assertTrue("Same thread session as before", holder.getSession() == ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession()); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); return null; } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); verify(session).close(); verify(tx).commit(); } @Test public void testTransactionWithPropagationSupports() throws Exception { final SessionFactory sf = mock(SessionFactory.class); final Session session = mock(Session.class); given(sf.openSession()).willReturn(session); given(session.getSessionFactory()).willReturn(sf); given(session.getFlushMode()).willReturn(FlushMode.MANUAL); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { @Override protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { return sf; } }; lsfb.afterPropertiesSet(); final SessionFactory sfProxy = lsfb.getObject(); PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); assertTrue("Is not new transaction", !status.isNewTransaction()); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); Session session = sf.openSession(); session.flush(); session.close(); return null; } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); InOrder ordered = inOrder(session); ordered.verify(session).flush(); ordered.verify(session).close(); } @Test public void testTransactionWithPropagationSupportsAndCurrentSession() throws Exception { final SessionFactoryImplementor sf = mock(SessionFactoryImplementor.class); final Session session = mock(Session.class); given(sf.openSession()).willReturn(session); given(session.getSessionFactory()).willReturn(sf); given(session.getFlushMode()).willReturn(FlushMode.MANUAL); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { @Override protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { return sf; } }; lsfb.afterPropertiesSet(); final SessionFactory sfProxy = lsfb.getObject(); PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); assertTrue("Is not new transaction", !status.isNewTransaction()); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); Session session = new SpringSessionContext(sf).currentSession(); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sfProxy)); session.flush(); return null; } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); InOrder ordered = inOrder(session); ordered.verify(session).flush(); ordered.verify(session).close(); } @Test public void testTransactionWithPropagationSupportsAndInnerTransaction() throws Exception { final SessionFactory sf = mock(SessionFactory.class); final ImplementingSession session1 = mock(ImplementingSession.class); final ImplementingSession session2 = mock(ImplementingSession.class); Connection con = mock(Connection.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session1, session2); given(session1.getSessionFactory()).willReturn(sf); given(session1.getFlushMode()).willReturn(FlushMode.AUTO); given(session2.beginTransaction()).willReturn(tx); given(session2.connection()).willReturn(con); given(session2.getFlushMode()).willReturn(FlushMode.AUTO); given(session2.isOpen()).willReturn(true); given(session2.isConnected()).willReturn(true); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { @Override protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { return sf; } }; lsfb.afterPropertiesSet(); final SessionFactory sfProxy = lsfb.getObject(); PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); final TransactionTemplate tt2 = new TransactionTemplate(tm); tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy)); assertTrue("Is not new transaction", !status.isNewTransaction()); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); Session session = sfProxy.openSession(); assertSame(session1, session); tt2.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); assertSame(session2, session); session.flush(); return null; } }); session.flush(); session.close(); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); return null; } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); verify(session1).flush(); verify(session1).close(); verify(session2).flush(); verify(session2).close(); verify(tx).commit(); } @Test public void testTransactionCommitWithEntityInterceptor() throws Exception { Interceptor entityInterceptor = mock(Interceptor.class); Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); SessionBuilder options = mock(SessionBuilder.class); Transaction tx = mock(Transaction.class); given(sf.withOptions()).willReturn(options); given(options.interceptor(entityInterceptor)).willReturn(options); given(options.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); HibernateTransactionManager tm = new HibernateTransactionManager(sf); tm.setEntityInterceptor(entityInterceptor); tm.setAllowResultAccessAfterCompletion(true); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(session).close(); verify(tx).commit(); } @Test public void testTransactionCommitWithEntityInterceptorBeanName() throws Exception { Interceptor entityInterceptor = mock(Interceptor.class); Interceptor entityInterceptor2 = mock(Interceptor.class); Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); SessionBuilder options = mock(SessionBuilder.class); Transaction tx = mock(Transaction.class); given(sf.withOptions()).willReturn(options); given(options.interceptor(entityInterceptor)).willReturn(options); given(options.interceptor(entityInterceptor2)).willReturn(options); given(options.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); BeanFactory beanFactory = mock(BeanFactory.class); given(beanFactory.getBean("entityInterceptor", Interceptor.class)).willReturn(entityInterceptor, entityInterceptor2); HibernateTransactionManager tm = new HibernateTransactionManager(sf); tm.setEntityInterceptorBeanName("entityInterceptor"); tm.setBeanFactory(beanFactory); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); for (int i = 0; i < 2; i++) { tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); } }); } assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(session, times(2)).close(); verify(tx, times(2)).commit(); } @Test public void testTransactionCommitWithReadOnly() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); Query query = mock(Query.class); final List list = new ArrayList(); list.add("test"); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.connection()).willReturn(con); given(session.isOpen()).willReturn(true); given(session.createQuery("some query string")).willReturn(query); given(query.list()).willReturn(list); given(session.isConnected()).willReturn(true); given(con.isReadOnly()).willReturn(true); HibernateTransactionManager tm = new HibernateTransactionManager(sf); TransactionTemplate tt = new TransactionTemplate(tm); tt.setReadOnly(true); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); Object result = tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); return session.createQuery("some query string").list(); } }); assertTrue("Correct result list", result == list); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(session).setFlushMode(FlushMode.MANUAL); verify(con).setReadOnly(true); verify(tx).commit(); verify(con).setReadOnly(false); verify(session).close(); } @Test public void testTransactionCommitWithFlushFailure() throws Exception { Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); SQLException sqlEx = new SQLException("argh", "27"); Exception rootCause = null; ConstraintViolationException jdbcEx = new ConstraintViolationException("mymsg", sqlEx, null); rootCause = jdbcEx; willThrow(jdbcEx).given(tx).commit(); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); HibernateTransactionManager tm = new HibernateTransactionManager(sf); TransactionTemplate tt = new TransactionTemplate(tm); final List l = new ArrayList(); l.add("test"); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); try { tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); return l; } }); fail("Should have thrown DataIntegrityViolationException"); } catch (DataIntegrityViolationException ex) { // expected assertEquals(rootCause, ex.getCause()); assertTrue(ex.getMessage().contains("mymsg")); } assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(session).close(); verify(tx).rollback(); } @Test public void testTransactionCommitWithPreBound() throws Exception { final DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); final ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.MANUAL); given(session.connection()).willReturn(con); given(con.getTransactionIsolation()).willReturn(Connection.TRANSACTION_READ_COMMITTED); given(session.isConnected()).willReturn(true); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.setDataSource(ds); TransactionTemplate tt = new TransactionTemplate(tm); tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); final List l = new ArrayList(); l.add("test"); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); Object result = tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Has thread transaction", sessionHolder.getTransaction() != null); Session sess = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); assertEquals(session, sess); return l; } }); assertTrue("Correct result list", result == l); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null); TransactionSynchronizationManager.unbindResource(sf); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); InOrder ordered = inOrder(session, con); ordered.verify(con).setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); ordered.verify(session).setFlushMode(FlushMode.AUTO); ordered.verify(con).setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); ordered.verify(session).setFlushMode(FlushMode.MANUAL); verify(tx).commit(); verify(session).disconnect(); } @Test public void testTransactionCommitWithPreBoundAndResultAccessAfterCommit() throws Exception { final DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); final ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); given(session.beginTransaction()).willReturn(tx); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.MANUAL); given(session.connection()).willReturn(con); given(con.getTransactionIsolation()).willReturn(Connection.TRANSACTION_READ_COMMITTED); given(con.getHoldability()).willReturn(ResultSet.CLOSE_CURSORS_AT_COMMIT); given(session.isConnected()).willReturn(true); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.setDataSource(ds); tm.setAllowResultAccessAfterCompletion(true); TransactionTemplate tt = new TransactionTemplate(tm); tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); final List l = new ArrayList(); l.add("test"); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); Object result = tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Has thread transaction", sessionHolder.getTransaction() != null); Session sess = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); assertEquals(session, sess); return l; } }); assertTrue("Correct result list", result == l); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null); TransactionSynchronizationManager.unbindResource(sf); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); InOrder ordered = inOrder(session, con); ordered.verify(con).setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); ordered.verify(con).setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); ordered.verify(session).setFlushMode(FlushMode.AUTO); ordered.verify(con).setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); ordered.verify(con).setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); ordered.verify(session).setFlushMode(FlushMode.MANUAL); verify(tx).commit(); } @Test public void testTransactionRollbackWithPreBound() throws Exception { final DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); final SessionFactory sf = mock(SessionFactory.class); final ImplementingSession session = mock(ImplementingSession.class); final Transaction tx1 = mock(Transaction.class); final Transaction tx2 = mock(Transaction.class); given(session.beginTransaction()).willReturn(tx1, tx2); given(session.isOpen()).willReturn(true); given(session.getFlushMode()).willReturn(FlushMode.MANUAL); given(session.isConnected()).willReturn(true); given(session.connection()).willReturn(con); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.setDataSource(ds); final TransactionTemplate tt = new TransactionTemplate(tm); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); try { tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertEquals(tx1, sessionHolder.getTransaction()); tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { status.setRollbackOnly(); Session sess = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); assertEquals(session, sess); } }); } }); fail("Should have thrown UnexpectedRollbackException"); } catch (UnexpectedRollbackException ex) { // expected } assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null); assertTrue("Not marked rollback-only", !sessionHolder.isRollbackOnly()); tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertEquals(tx2, sessionHolder.getTransaction()); Session sess = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); assertEquals(session, sess); } }); assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null); TransactionSynchronizationManager.unbindResource(sf); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(tx1).rollback(); verify(tx2).commit(); InOrder ordered = inOrder(session); ordered.verify(session).clear(); ordered.verify(session).setFlushMode(FlushMode.AUTO); ordered.verify(session).setFlushMode(FlushMode.MANUAL); ordered.verify(session).disconnect(); } @Test public void testTransactionRollbackWithHibernateManagedSession() throws Exception { final SessionFactory sf = mock(SessionFactory.class); final Session session = mock(Session.class); final Transaction tx1 = mock(Transaction.class); final Transaction tx2 = mock(Transaction.class); given(sf.getCurrentSession()).willReturn(session); given(session.isOpen()).willReturn(true); given(session.getTransaction()).willReturn(tx1, tx2); given(session.beginTransaction()).willReturn(tx1, tx2); given(session.getFlushMode()).willReturn(FlushMode.MANUAL); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.setPrepareConnection(false); tm.setHibernateManagedSession(true); final TransactionTemplate tt = new TransactionTemplate(tm); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); try { tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { status.setRollbackOnly(); Session sess = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); assertEquals(session, sess); } }); } }); fail("Should have thrown UnexpectedRollbackException"); } catch (UnexpectedRollbackException ex) { // expected } assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); Session sess = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); assertEquals(session, sess); } }); verify(tx1).rollback(); verify(tx2).commit(); InOrder ordered = inOrder(session); ordered.verify(session).setFlushMode(FlushMode.AUTO); ordered.verify(session).setFlushMode(FlushMode.MANUAL); } @Test public void testExistingTransactionWithPropagationNestedAndRollback() throws Exception { doTestExistingTransactionWithPropagationNestedAndRollback(false); } @Test public void testExistingTransactionWithManualSavepointAndRollback() throws Exception { doTestExistingTransactionWithPropagationNestedAndRollback(true); } private void doTestExistingTransactionWithPropagationNestedAndRollback(final boolean manualSavepoint) throws Exception { final DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); DatabaseMetaData md = mock(DatabaseMetaData.class); Savepoint sp = mock(Savepoint.class); final SessionFactory sf = mock(SessionFactory.class); ImplementingSession session = mock(ImplementingSession.class); Transaction tx = mock(Transaction.class); Query query = mock(Query.class); final List list = new ArrayList(); list.add("test"); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); given(session.connection()).willReturn(con); given(session.isOpen()).willReturn(true); given(md.supportsSavepoints()).willReturn(true); given(con.getMetaData()).willReturn(md); given(con.setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1)).willReturn(sp); given(session.createQuery("some query string")).willReturn(query); given(query.list()).willReturn(list); given(session.isConnected()).willReturn(true); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setNestedTransactionAllowed(true); tm.setSessionFactory(sf); tm.setDataSource(ds); final TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); Object result = tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); if (manualSavepoint) { Object savepoint = status.createSavepoint(); status.rollbackToSavepoint(savepoint); } else { tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); status.setRollbackOnly(); } }); } Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); return session.createQuery("some query string").list(); } }); assertTrue("Correct result list", result == list); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(con).setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1); verify(con).rollback(sp); verify(session).close(); verify(tx).commit(); } @Test public void testTransactionCommitWithNonExistingDatabase() throws Exception { final DriverManagerDataSource ds = new DriverManagerDataSource(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean(); lsfb.setDataSource(ds); Properties props = new Properties(); props.setProperty("hibernate.dialect", HSQLDialect.class.getName()); lsfb.setHibernateProperties(props); lsfb.afterPropertiesSet(); final SessionFactory sf = lsfb.getObject(); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.afterPropertiesSet(); TransactionTemplate tt = new TransactionTemplate(tm); tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); tt.setTimeout(10); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); try { tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); return session.createQuery("from java.lang.Object").list(); } }); fail("Should have thrown CannotCreateTransactionException"); } catch (CannotCreateTransactionException ex) { // expected } assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); } @Test public void testTransactionCommitWithPreBoundSessionAndNonExistingDatabase() throws Exception { final DriverManagerDataSource ds = new DriverManagerDataSource(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean(); lsfb.setDataSource(ds); Properties props = new Properties(); props.setProperty("hibernate.dialect", HSQLDialect.class.getName()); lsfb.setHibernateProperties(props); lsfb.afterPropertiesSet(); final SessionFactory sf = lsfb.getObject(); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.afterPropertiesSet(); TransactionTemplate tt = new TransactionTemplate(tm); tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); tt.setTimeout(10); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); Session session = sf.openSession(); TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); try { tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)) .getSession(); return session.createQuery("from java.lang.Object").list(); } }); fail("Should have thrown CannotCreateTransactionException"); } catch (CannotCreateTransactionException ex) { // expected SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); assertFalse(holder.isSynchronizedWithTransaction()); } finally { TransactionSynchronizationManager.unbindResource(sf); session.close(); } assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); } @Test public void testTransactionCommitWithNonExistingDatabaseAndLazyConnection() throws Exception { DriverManagerDataSource dsTarget = new DriverManagerDataSource(); final LazyConnectionDataSourceProxy ds = new LazyConnectionDataSourceProxy(); ds.setTargetDataSource(dsTarget); ds.setDefaultAutoCommit(true); ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); //ds.setDefaultTransactionIsolationName("TRANSACTION_READ_COMMITTED"); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean(); lsfb.setDataSource(ds); Properties props = new Properties(); props.setProperty("hibernate.dialect", HSQLDialect.class.getName()); props.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false"); lsfb.setHibernateProperties(props); lsfb.afterPropertiesSet(); final SessionFactory sf = lsfb.getObject(); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.setSessionFactory(sf); tm.afterPropertiesSet(); TransactionTemplate tt = new TransactionTemplate(tm); tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); tt.setTimeout(10); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); tt.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); Session session = ((SessionHolder) TransactionSynchronizationManager.getResource(sf)).getSession(); return session.createQuery("from java.lang.Object").list(); } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); } @Test public void testTransactionFlush() throws Exception { final SessionFactory sf = mock(SessionFactory.class); final Session session = mock(Session.class); Transaction tx = mock(Transaction.class); given(sf.openSession()).willReturn(session); given(session.beginTransaction()).willReturn(tx); HibernateTransactionManager tm = new HibernateTransactionManager(sf); tm.setPrepareConnection(false); TransactionTemplate tt = new TransactionTemplate(tm); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); tt.execute(new TransactionCallbackWithoutResult() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); status.flush(); } }); assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(session).flush(); verify(tx).commit(); verify(session).close(); } @Test public void testSetJtaTransactionManager() throws Exception { DataSource ds = mock(DataSource.class); TransactionManager tm = mock(TransactionManager.class); UserTransaction ut = mock(UserTransaction.class); TransactionSynchronizationRegistry tsr = mock(TransactionSynchronizationRegistry.class); JtaTransactionManager jtm = new JtaTransactionManager(); jtm.setTransactionManager(tm); jtm.setUserTransaction(ut); jtm.setTransactionSynchronizationRegistry(tsr); LocalSessionFactoryBuilder lsfb = new LocalSessionFactoryBuilder(ds); lsfb.setJtaTransactionManager(jtm); Object jtaPlatform = lsfb.getProperties().get(AvailableSettings.JTA_PLATFORM); assertNotNull(jtaPlatform); assertSame(tm, jtaPlatform.getClass().getMethod("retrieveTransactionManager").invoke(jtaPlatform)); assertSame(ut, jtaPlatform.getClass().getMethod("retrieveUserTransaction").invoke(jtaPlatform)); assertTrue( lsfb.getProperties().get(AvailableSettings.TRANSACTION_STRATEGY) instanceof CMTTransactionFactory); } @Test public void testSetTransactionManager() throws Exception { DataSource ds = mock(DataSource.class); TransactionManager tm = mock(TransactionManager.class); LocalSessionFactoryBuilder lsfb = new LocalSessionFactoryBuilder(ds); lsfb.setJtaTransactionManager(tm); Object jtaPlatform = lsfb.getProperties().get(AvailableSettings.JTA_PLATFORM); assertNotNull(jtaPlatform); assertSame(tm, jtaPlatform.getClass().getMethod("retrieveTransactionManager").invoke(jtaPlatform)); assertTrue( lsfb.getProperties().get(AvailableSettings.TRANSACTION_STRATEGY) instanceof CMTTransactionFactory); } public interface ImplementingSession extends Session, SessionImplementor { } }