HibernateTemplate 、bulkUpdate 和刷新模式

发布于 2025-01-04 22:42:21 字数 6052 浏览 2 评论 0原文

我们在当前项目中使用 hibernateTemplate 作为我们的 dao。我有一种情况,如果事务中的任一操作失败,我希望事务回滚(不是火箭科学,对吧?)..所以基本上,这是方法:

    // Reserve a deal and add the 'pending order' all in one transaction
@Transactional(propagation = Propagation.REQUIRES_NEW)
private MyUserOrder reserveQuantity(MyUserOrder userOrder, Date updatedOn) throws MyAPIException{

    userOrder.setOrderStatus(OrderStatus.PENDING);
    int orderReserved = orderDao.reserveQuantity(userOrder);

    //for some reason hibernate is flushing on the above line???

    if (dealsReserved < 1)
            throw new MyAPIException(ExceptionCode.INSUFFICIENT_QUANTITY);

    userOrder = userOrderDao.save(userOrder);

    //hibernate flushes again!

    return userOrder;
}

所以,基本上我们从数据库订单中保留 X 订单可用性表...然后将挂单保存到数据库。我希望这两个语句在同一事务中执行,因此如果其中一个语句失败,它们都会回滚。不幸的是,看起来 .reserveQuantity 的语句正在立即提交,即使整个方法应该在它自己的事务中运行。

这是日志..

    13:09:28.007 [5253145@qtp-25442933-1] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13291529680
13:09:28.008 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Registering Spring transaction synchronization for new Hibernate Session
13:09:28.009 [5253145@qtp-25442933-1] DEBUG o.s.orm.hibernate3.HibernateTemplate - Found thread-bound Session for HibernateTemplate
13:09:28.011 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
13:09:28.011 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection
13:09:28.012 [5253145@qtp-25442933-1] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:db2://172.26.10.144:60000/devdb]
13:09:28.189 [5253145@qtp-25442933-1] DEBUG org.hibernate.SQL - update deal set remaining_quantity=remaining_quantity-?, updated_on=?, updated_by=? where id=? and remaining_quantity>=?
13:09:28.242 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
13:09:28.243 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
13:09:28.244 [5253145@qtp-25442933-1] DEBUG o.s.orm.hibernate3.HibernateTemplate - Not closing pre-bound Hibernate Session after HibernateTemplate
13:09:28.245 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Flushing Hibernate Session on transaction synchronization
13:09:28.246 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Registering Hibernate Session for deferred close
13:09:30.524 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Opening Hibernate Session
13:09:30.525 [5253145@qtp-25442933-1] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13291529705
13:09:30.534 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.537 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.540 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.543 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.549 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.551 [5253145@qtp-25442933-1] DEBUG o.s.orm.hibernate3.HibernateTemplate - Eagerly flushing Hibernate session
13:09:30.552 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - processing flush-time cascades
13:09:30.554 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - dirty checking collections
13:09:30.556 [5253145@qtp-25442933-1] DEBUG org.hibernate.engine.Collections - Collection found: [<redacted>.UserOrder.dealOrderSet#<delayed:8>], was: [<unreferenced>] (initialized)
13:09:30.558 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - Flushed: 5 insertions, 0 updates, 0 deletions to 5 objects
13:09:30.559 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - Flushed: 1 (re)creations, 0 updates, 0 removals to 1 collections

如您所见,发生了两次刷新操作.. 一次大约在日志的中间(当我保留时),另一次在最后当我尝试保存订单 bean 时。这是我的数据源配置。

    <bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dealsdbDataSource" />
    <property name="packagesToScan" value="<redacted>.common"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.archive.autodetection">class</prop>
            <prop key="hibernate.show_sql">${hibernate-show-sql}</prop>
            <prop key="hibernate.format_sql">false</prop>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.hbm2ddl.import_files">${hibernate.hbm2ddl.import_files}</prop>
        </props>
    </property>
</bean>

<bean id="hibernateTemplate" name="hibernateTemplate"
    class="org.springframework.orm.hibernate3.HibernateTemplate">
    <constructor-arg ref="sessionFactory" />               
</bean>

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

<tx:annotation-driven transaction-manager="transactionManager"/>

另外经过调查,看起来我的刷新模式在 hibernateTemplate 中是自动的。

有什么想法吗?

We are using hibernateTemplate for our dao's within my current project. I have a situation where I want to have a transaction that rolls back if either operation within the transaction fails (not rocket science, right?).. so basically, here is the method:

    // Reserve a deal and add the 'pending order' all in one transaction
@Transactional(propagation = Propagation.REQUIRES_NEW)
private MyUserOrder reserveQuantity(MyUserOrder userOrder, Date updatedOn) throws MyAPIException{

    userOrder.setOrderStatus(OrderStatus.PENDING);
    int orderReserved = orderDao.reserveQuantity(userOrder);

    //for some reason hibernate is flushing on the above line???

    if (dealsReserved < 1)
            throw new MyAPIException(ExceptionCode.INSUFFICIENT_QUANTITY);

    userOrder = userOrderDao.save(userOrder);

    //hibernate flushes again!

    return userOrder;
}

So, basically we reserve X orders from the databases order availability table... and then save the pending order to the database. I'd like both statements to execute in the same transaction, so if one fails they both roll back. Unfortunately, it looks like the statement for .reserveQuantity is being committed immediately, even though the whole method should run within it's own transaction.

Here is the log..

    13:09:28.007 [5253145@qtp-25442933-1] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13291529680
13:09:28.008 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Registering Spring transaction synchronization for new Hibernate Session
13:09:28.009 [5253145@qtp-25442933-1] DEBUG o.s.orm.hibernate3.HibernateTemplate - Found thread-bound Session for HibernateTemplate
13:09:28.011 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
13:09:28.011 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection
13:09:28.012 [5253145@qtp-25442933-1] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:db2://172.26.10.144:60000/devdb]
13:09:28.189 [5253145@qtp-25442933-1] DEBUG org.hibernate.SQL - update deal set remaining_quantity=remaining_quantity-?, updated_on=?, updated_by=? where id=? and remaining_quantity>=?
13:09:28.242 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
13:09:28.243 [5253145@qtp-25442933-1] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
13:09:28.244 [5253145@qtp-25442933-1] DEBUG o.s.orm.hibernate3.HibernateTemplate - Not closing pre-bound Hibernate Session after HibernateTemplate
13:09:28.245 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Flushing Hibernate Session on transaction synchronization
13:09:28.246 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Registering Hibernate Session for deferred close
13:09:30.524 [5253145@qtp-25442933-1] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Opening Hibernate Session
13:09:30.525 [5253145@qtp-25442933-1] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13291529705
13:09:30.534 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.537 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.540 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.543 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.549 [5253145@qtp-25442933-1] DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
13:09:30.551 [5253145@qtp-25442933-1] DEBUG o.s.orm.hibernate3.HibernateTemplate - Eagerly flushing Hibernate session
13:09:30.552 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - processing flush-time cascades
13:09:30.554 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - dirty checking collections
13:09:30.556 [5253145@qtp-25442933-1] DEBUG org.hibernate.engine.Collections - Collection found: [<redacted>.UserOrder.dealOrderSet#<delayed:8>], was: [<unreferenced>] (initialized)
13:09:30.558 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - Flushed: 5 insertions, 0 updates, 0 deletions to 5 objects
13:09:30.559 [5253145@qtp-25442933-1] DEBUG o.h.e.d.AbstractFlushingEventListener - Flushed: 1 (re)creations, 0 updates, 0 removals to 1 collections

As you can see, two flush operations occurred.. one about halfway through the log (when I reserve) and another at the end when I try to save the order bean. Here is my data sources config.

    <bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dealsdbDataSource" />
    <property name="packagesToScan" value="<redacted>.common"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.archive.autodetection">class</prop>
            <prop key="hibernate.show_sql">${hibernate-show-sql}</prop>
            <prop key="hibernate.format_sql">false</prop>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.hbm2ddl.import_files">${hibernate.hbm2ddl.import_files}</prop>
        </props>
    </property>
</bean>

<bean id="hibernateTemplate" name="hibernateTemplate"
    class="org.springframework.orm.hibernate3.HibernateTemplate">
    <constructor-arg ref="sessionFactory" />               
</bean>

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

<tx:annotation-driven transaction-manager="transactionManager"/>

Also upon investigation, it looks like my flushmode is AUTO in hibernateTemplate.

Any ideas??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

世界等同你 2025-01-11 22:42:21

请检查您是否在 orderDao 类中声明了 @Transactional 。
我想这可能就是原因。

最佳实践是在服务层使用@Transactional,而不是在DAO 层使用@Transactional。

Can you please check , if you have declared @Transactional in the orderDao class.
I suppose that could be the cause.

best practice is to have @Transactional at the service layer and not to have any at the DAO layer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文