开发者

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 开发者_如何学Cit.

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>


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜