Example usage for org.hibernate FlushMode MANUAL

List of usage examples for org.hibernate FlushMode MANUAL

Introduction

In this page you can find the example usage for org.hibernate FlushMode MANUAL.

Prototype

FlushMode MANUAL

To view the source code for org.hibernate FlushMode MANUAL.

Click Source Link

Document

The Session is only ever flushed when Session#flush is explicitly called by the application.

Usage

From source file:org.springframework.orm.hibernate3.support.OpenSessionInViewTests.java

License:Apache License

@Test
public void testOpenSessionInViewFilterWithDeferredClose() 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);

    final SessionFactory sf2 = mock(SessionFactory.class);
    final Session session2 = mock(Session.class);

    Transaction tx = mock(Transaction.class);
    Connection con = mock(Connection.class);

    given(sf2.openSession()).willReturn(session2);
    given(session2.connection()).willReturn(con);
    given(session2.beginTransaction()).willReturn(tx);
    given(session2.isConnected()).willReturn(true);
    given(session2.connection()).willReturn(con);

    StaticWebApplicationContext wac = new StaticWebApplicationContext();
    wac.setServletContext(sc);//w ww  . j av a 2s .co  m
    wac.getDefaultListableBeanFactory().registerSingleton("sessionFactory", sf);
    wac.getDefaultListableBeanFactory().registerSingleton("mySessionFactory", sf2);
    wac.refresh();
    sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);

    MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
    MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
    filterConfig.addInitParameter("singleSession", "false");
    filterConfig2.addInitParameter("singleSession", "false");
    filterConfig2.addInitParameter("sessionFactoryBeanName", "mySessionFactory");

    final OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
    filter.init(filterConfig);
    final OpenSessionInViewFilter filter2 = new OpenSessionInViewFilter();
    filter2.init(filterConfig2);

    final FilterChain filterChain = new FilterChain() {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
            HibernateTransactionManager tm = new HibernateTransactionManager(sf);
            TransactionStatus ts = tm.getTransaction(
                    new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
            org.hibernate.Session sess = SessionFactoryUtils.getSession(sf, true);
            SessionFactoryUtils.releaseSession(sess, sf);
            tm.commit(ts);
            servletRequest.setAttribute("invoked", Boolean.TRUE);
        }
    };

    final FilterChain filterChain2 = new FilterChain() {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
                throws IOException, ServletException {
            HibernateTransactionManager tm = new HibernateTransactionManager(sf2);
            TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
            tm.commit(ts);
            filter.doFilter(servletRequest, servletResponse, filterChain);
        }
    };

    FilterChain filterChain3 = new PassThroughFilterChain(filter2, filterChain2);

    filter2.doFilter(this.request, this.response, filterChain3);
    assertNotNull(this.request.getAttribute("invoked"));

    verify(session).setFlushMode(FlushMode.MANUAL);
    verify(tx).commit();
    verify(session2).setFlushMode(FlushMode.MANUAL);
    verify(session).close();
    verify(session2).close();

    wac.close();
}

From source file:org.springframework.orm.hibernate3.support.OpenSessionInViewTests.java

License:Apache License

@Test
public void testOpenSessionInViewFilterWithDeferredCloseAndAlreadyActiveDeferredClose() 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);

    StaticWebApplicationContext wac = new StaticWebApplicationContext();
    wac.setServletContext(sc);//from   w w  w .  j  a  v  a2  s  . c  om
    wac.getDefaultListableBeanFactory().registerSingleton("sessionFactory", sf);
    wac.refresh();
    sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);

    MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
    MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
    filterConfig.addInitParameter("singleSession", "false");
    filterConfig2.addInitParameter("singleSession", "false");
    filterConfig2.addInitParameter("sessionFactoryBeanName", "mySessionFactory");

    OpenSessionInViewInterceptor interceptor = new OpenSessionInViewInterceptor();
    interceptor.setSessionFactory(sf);
    interceptor.setSingleSession(false);

    interceptor.preHandle(webRequest);

    final OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
    filter.init(filterConfig);
    final OpenSessionInViewFilter filter2 = new OpenSessionInViewFilter();
    filter2.init(filterConfig2);

    final FilterChain filterChain = new FilterChain() {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
            HibernateTransactionManager tm = new HibernateTransactionManager(sf);
            TransactionStatus ts = tm.getTransaction(
                    new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
            org.hibernate.Session sess = SessionFactoryUtils.getSession(sf, true);
            SessionFactoryUtils.releaseSession(sess, sf);
            tm.commit(ts);
            servletRequest.setAttribute("invoked", Boolean.TRUE);
        }
    };

    FilterChain filterChain2 = new FilterChain() {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
                throws IOException, ServletException {
            filter.doFilter(servletRequest, servletResponse, filterChain);
        }
    };

    filter.doFilter(this.request, this.response, filterChain2);
    assertNotNull(this.request.getAttribute("invoked"));

    interceptor.postHandle(webRequest, null);
    interceptor.afterCompletion(webRequest, null);

    verify(session).setFlushMode(FlushMode.MANUAL);
    verify(session).close();

    wac.close();
}

From source file:org.springframework.orm.hibernate4.fix.HibernateTransactionManager.java

License:Apache License

@Override
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.");
    }/*from   w  ww.j a  va2  s. c  om*/

    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);
        } 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 = session.getFlushMode();
            if (FlushMode.MANUAL.equals(session.getFlushMode())) {
                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().isActive()) {
                    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);
    }
}

From source file:org.springframework.orm.hibernate4.fix.SpringSessionContext.java

License:Apache License

/**
 * Retrieve the Spring-managed Session for the current thread, if any.
 */// ww w  .  ja v  a2s.c om
public Session currentSession() throws HibernateException {
    Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
    if (value instanceof Session) {
        return (Session) value;
    } else if (value instanceof SessionHolder) {
        SessionHolder sessionHolder = (SessionHolder) value;
        Session session = sessionHolder.getSession();
        if (!sessionHolder.isSynchronizedWithTransaction()
                && TransactionSynchronizationManager.isSynchronizationActive()) {
            TransactionSynchronizationManager.registerSynchronization(
                    new SpringSessionSynchronization(sessionHolder, this.sessionFactory));
            sessionHolder.setSynchronizedWithTransaction(true);
            // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
            // with FlushMode.MANUAL, which needs to allow flushing within the transaction.
            FlushMode flushMode = session.getFlushMode();
            if (FlushMode.MANUAL.equals(flushMode)
                    && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                session.setFlushMode(FlushMode.AUTO);
                sessionHolder.setPreviousFlushMode(flushMode);
            }
        }
        return session;
    } else if (this.jtaSessionContext != null) {
        Session session = this.jtaSessionContext.currentSession();
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));
        }
        return session;
    } else {
        throw new HibernateException("No Session found for current thread");
    }
}

From source file:org.springframework.orm.hibernate4.fix.SpringSessionSynchronization.java

License:Apache License

public void beforeCommit(boolean readOnly) throws DataAccessException {
    if (!readOnly) {
        Session session = getCurrentSession();
        // Read-write transaction -> flush the Hibernate Session.
        // Further check: only flush when not FlushMode.MANUAL.
        if (!FlushMode.MANUAL.equals(session.getFlushMode())) {
            try {
                SessionFactoryUtils.logger.debug("Flushing Hibernate Session on transaction synchronization");
                session.flush();//from  w  ww.j  av  a  2s  .  c  o m
            } catch (HibernateException ex) {
                throw SessionFactoryUtils.convertHibernateAccessException(ex);
            }
        }
    }
}

From source file:org.springframework.orm.hibernate4.HibernateTemplate.java

License:Apache License

/**
 * Execute the action specified by the given action object within a Session.
 * @param action callback object that specifies the Hibernate action
 * @param enforceNativeSession whether to enforce exposure of the native
 * Hibernate Session to callback code// w ww .  ja  v  a  2  s  .  co m
 * @return a result object returned by the action, or {@code null}
 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors
 */
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNativeSession)
        throws DataAccessException {
    Assert.notNull(action, "Callback object must not be null");

    Session session = null;
    boolean isNew = false;
    try {
        session = getSessionFactory().getCurrentSession();
    } catch (HibernateException ex) {
        logger.debug("Could not retrieve pre-bound Hibernate session", ex);
    }
    if (session == null) {
        session = getSessionFactory().openSession();
        session.setFlushMode(FlushMode.MANUAL);
        isNew = true;
    }

    try {
        enableFilters(session);
        Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session
                : createSessionProxy(session));
        return action.doInHibernate(sessionToExpose);
    } catch (HibernateException ex) {
        throw SessionFactoryUtils.convertHibernateAccessException(ex);
    } catch (RuntimeException ex) {
        // Callback code threw application exception...
        throw ex;
    } finally {
        if (isNew) {
            SessionFactoryUtils.closeSession(session);
        } else {
            disableFilters(session);
        }
    }
}

From source file:org.springframework.orm.hibernate4.HibernateTemplateTests.java

License:Apache License

@Test
public void testSaveOrUpdateWithFlushModeNever() {
    TestBean tb = new TestBean();
    given(session.getFlushMode()).willReturn(FlushMode.MANUAL);
    try {//  w  ww. j av a  2s  .  c  o  m
        hibernateTemplate.saveOrUpdate(tb);
        fail("Should have thrown InvalidDataAccessApiUsageException");
    } catch (InvalidDataAccessApiUsageException ex) {
        // expected
    }
}

From source file:org.springframework.orm.hibernate4.HibernateTransactionManager.java

License:Apache License

@Override
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.");
    }//  www .j av a 2s .c om

    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 = session.getFlushMode();
            if (session.getFlushMode().equals(FlushMode.MANUAL)) {
                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().isActive()) {
                    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);
    }
}

From source file:org.springframework.orm.hibernate4.HibernateTransactionManagerTests.java

License:Apache License

@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//from  w  w  w. j  a va 2s.  c o m
        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();
}

From source file:org.springframework.orm.hibernate4.HibernateTransactionManagerTests.java

License:Apache License

@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//from  w  w w.j a  v  a  2  s .  com
        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();
}