简体   繁体   中英

After executing hibernate Interceptor it close session manage by spring transaction

I am working on upgrading spring and hibernate from version 3.x to 4.x. So everything works fine in older version but after upgrading to newer version I got a strange error.

Right now the problem is seems with the interceptor according to my research. If I comment out hibernate interceptor than everything works fine.

How problem occurs : I am using spring managed transaction all over the application and also accessing spring services in hibernate interceptor with ApplicationContextAware. So if any single query get executed from interceptor than from the next query it gives me an error that session is close. If I comment out the query from interceptor than every thing works find as I stated again.

I have multiple session factory and transaction manager. My configuration is as below :

<bean class="com.test.MyInterceptor">
<constructor-arg type="java.lang.String" value="my_config" />
/bean>
<bean id="sf" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="Ds"/>
    <property name="mappingResources">
        <list>
            <value>....</value>
        </list>
    </property>
    <property name="entityInterceptor" ref="myInterceptor" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">...</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.c3p0.minPoolSize">...</prop>
            <prop key="hibernate.c3p0.maxPoolSize">...</prop>
            <prop key="hibernate.c3p0.timeout">120</prop>
            <prop key="hibernate.c3p0.max_statement">..</prop>
            <prop key="hibernate.c3p0.unreturnedConnectionTimeout">600</prop>
            <prop key="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</prop>
            <prop key="hibernate.hbm2ddl.auto">none</prop>
            <prop key="hibernate.c3p0.testConnectionOnCheckin">false</prop>
            <prop key="hibernate.c3p0.testConnectionOnCheckout">true</prop>
            <prop key="hibernate.default_batch_fetch_size">5</prop>
        </props>
    </property>
</bean>

<bean id="transactionTx" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sf"/>
</bean>

My interceptor and service looks like :

public class MyInterceptor extends EmptyInterceptor implements ApplicationContextAware {

private ApplicationContext context;
    @Override
    protected void handleAfterTransactionCompletion(Transaction arg0) throws CallbackException {
        // after executing this it breaks my spring transaction.
        Entity entity = service.get(id);
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context = context;
    }
}

public class ServiceImple {

......................
...................

    @Transactional
    public Entity get(long id) {
        return dao.get(id);
    }
}

Error stack trace is :

(main)  SessionImpl ERROR: HHH000087: Exception in interceptor afterTransactionCompletion()
org.springframework.orm.hibernate4.HibernateSystemException: This TransactionCoordinator has been closed; nested exception is org.hibernate.ResourceClosedException: This TransactionCoordinator has been closed
    at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:218)
    at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:344)
    at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:309)
    at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:419)
    at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:412)
    at code......................
    at sun.reflect.GeneratedMethodAccessor95.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy70.get(Unknown Source)
    at code......................
    at org.hibernate.internal.SessionImpl.afterTransactionCompletion(SessionImpl.java:508)
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.afterTransaction(TransactionCoordinatorImpl.java:151)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.afterTransactionCompletion(JdbcTransaction.java:138)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
Caused by: org.hibernate.ResourceClosedException: This TransactionCoordinator has been closed
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.getTransaction(TransactionCoordinatorImpl.java:191)
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.isTransactionInProgress(TransactionCoordinatorImpl.java:167)
    at org.hibernate.internal.SessionImpl.afterOperation(SessionImpl.java:476)
    at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2456)
    at org.hibernate.internal.SessionImpl.get(SessionImpl.java:949)
    at org.springframework.orm.hibernate4.HibernateTemplate$1.doInHibernate(HibernateTemplate.java:427)
    at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:341)

Configuration is right I just written necessary class, let us know if required more.Any help will be appreciated.

From NHibernate documentation :

Interceptors come in two flavors: ISession-scoped and ISessionFactory-scoped.

An ISession-scoped interceptor is specified when a session is opened using one of the overloaded ISessionFactory.OpenSession() methods accepting an IInterceptor.

ISession session = sf.OpenSession( new AuditInterceptor() );

An ISessionFactory-scoped interceptor is registered with the Configuration object prior to building the ISessionFactory. In this case, the supplied interceptor will be applied to all sessions opened from that ISessionFactory; this is true unless a session is opened explicitly specifying the interceptor to use. ISessionFactory-scoped interceptors must be thread safe, taking care to not store session-specific state since multiple sessions will use this interceptor (potentially) concurrently.

new Configuration().SetInterceptor( new AuditInterceptor() );

So, basically you may check transaction is committed or what:

if ( tx.WasCommitted ) {
// do stuff
}

You also may override

public override bool OnSave(object entity, 
                                object id, 
                                object[] state,
                                string[] propertyNames,
                                IType[] types)
{
  //get entity with
       if ( entity is Entity ) {
               get entity properties: Id etc..
            }
}

to get Entity information.

I hope it will help...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM