简体   繁体   中英

hibernate/spring is trying to insert rather than save (record already exists in db) after the previous transaction failed

I have a batch interface class that creates a hibernate Session like this:

Session session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));

Then it calls a service to get a list of objects from the DB, and in the batch class it iterates through that list and for each object it makes a service call to do some processing against the object.

Say on the 2nd object some nullpointerexception occurs somewhere, and i catch the exception in my batch class. Then i try to process the 3rd object and in the service when it tries to save the object, by calling HibernateDaoSupport.getSession(false).save(object) - it actually tries to insert it (and i get an error because a record already exists) instead of updating it.

This only happens if the previous object failed. If an exception occurs does it do something w/ that Hibernate session? Any ideas whats going on?

I have the following in my app context.xml

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="*" rollback-for="Throwable"/>
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="serviceMethods" expression="execution(* com.company.service..*.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>

Let spring create your session and manage your transactions. The TransactionSynchornizationManager is something that you should not normally use.

Session.save is supposed to assign an identifier to a transient instance and persisting it by doing an insert. I'm rather surprised that it doesn't do this in your first service call.

And since a NPE occurs in your service call, the transaction is rolled back (since you configured it with <tx:method name="*" rollback-for="Throwable"/> ), which could explain some differences between the succeeding calls and the failing ones. I don't know what your two first lines of code are supposed to do, but as Bozho said, you should not bind resources to the TransactionSynchronizationManager yourself. It's Spring's responsibility.

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