diff --git a/src/java/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java b/src/java/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java index a2c821ebfa0..de6611aec23 100644 --- a/src/java/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java +++ b/src/java/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java @@ -34,12 +34,13 @@ public class HibernatePersistenceContextInterceptor implements PersistenceContex private static final Log LOG = LogFactory.getLog(HibernatePersistenceContextInterceptor.class); private SessionFactory sessionFactory; private boolean participate; + private int nestingCount = 0; /* (non-Javadoc) * @see org.codehaus.groovy.grails.support.PersistenceContextInterceptor#destroy() */ public void destroy() { - if (participate) { + if (--nestingCount > 0 || participate) { return; } @@ -98,6 +99,9 @@ public boolean isOpen() { * @see org.codehaus.groovy.grails.support.PersistenceContextInterceptor#init() */ public void init() { + if (++nestingCount > 1) { + return; + } if (TransactionSynchronizationManager.hasResource(sessionFactory)) { // Do not modify the Session: just set the participate flag. participate = true; diff --git a/src/test/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptorTests.groovy b/src/test/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptorTests.groovy new file mode 100644 index 00000000000..3439cfce610 --- /dev/null +++ b/src/test/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptorTests.groovy @@ -0,0 +1,62 @@ +package org.codehaus.groovy.grails.orm.hibernate.support + +import org.codehaus.groovy.grails.orm.hibernate.AbstractGrailsHibernateTests +import org.springframework.transaction.support.TransactionSynchronizationManager +import org.springframework.orm.hibernate3.SessionFactoryUtils +import org.springframework.orm.hibernate3.SessionHolder +import org.hibernate.Session +import org.hibernate.SessionFactory +import java.util.concurrent.CountDownLatch + +/** + * @author Luke Daley + * @since 1.4 + */ +class HibernatePersistenceContextInterceptorTests extends AbstractGrailsHibernateTests { + + protected void setUp() { + super.setUp() + + // We are going to manage the session ourselves through the interceptor + def holder = TransactionSynchronizationManager.getResource(sessionFactory) + def s = holder.session + TransactionSynchronizationManager.unbindResource(sessionFactory) + SessionFactoryUtils.releaseSession(s, sessionFactory) + } + + void testSimpleLifecycle() { + def interceptor = getInterceptor() + assertEquals("interceptor open", false, interceptor.open) + interceptor.init() + assertEquals("interceptor open", true, interceptor.open) + interceptor.destroy() + assertEquals("interceptor open", false, interceptor.open) + interceptor.init() + assertEquals("interceptor open", true, interceptor.open) + interceptor.destroy() + assertEquals("interceptor open", false, interceptor.open) + } + + void testNestedLifecycle() { + def interceptor = getInterceptor() + assertEquals("interceptor open", false, interceptor.open) + + interceptor.init() + assertEquals("interceptor open", true, interceptor.open) + interceptor.init() + assertEquals("interceptor open", true, interceptor.open) + interceptor.destroy() + assertEquals("interceptor open", true, interceptor.open) + interceptor.destroy() + assertEquals("interceptor open", false, interceptor.open) + + interceptor.init() + assertEquals("interceptor open", true, interceptor.open) + interceptor.destroy() + assertEquals("interceptor open", false, interceptor.open) + } + + protected getInterceptor() { + appCtx.persistenceInterceptor + } +}