【问题标题】:Spring 4 + Hibernate 5.1 Transaction auto committed after call another DAO querySpring 4 + Hibernate 5.1 事务在调用另一个 DAO 查询后自动提交
【发布时间】:2016-05-14 08:54:49
【问题描述】:

在调用另一个 dao 本机查询后,我遇到事务自动提交的问题。

service 和 dao 都签名为 @Transactional。

我在这里做错了什么?

春季 4.2.x

休眠 5.1.0

Atomikos 3.9.3

这是我的设置:

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

<bean id="jtaPlatformAdapter" class="com.xxx.JtaPlatformAdapter">
    <property name="jtaTransactionManager" ref="transactionManager" />
</bean>

<bean class="com.atomikos.icatch.jta.UserTransactionManager" destroy-method="close" id="atomikosTransactionManager" init-method="init">
    <property name="forceShutdown" value="true" />
    <property name="startupTransactionService" value="true" />
</bean>

<bean class="com.atomikos.icatch.jta.UserTransactionImp" id="atomikosUserTransaction" />

<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="transactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
</bean>


<bean id="datasouce" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
    ...
</bean>

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" id="JPAVendorAdapter">
    ...
</bean>

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="emf" depends-on="transactionManager,jtaPlatformAdapter">
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
    <property name="packagesToScan" value="com.xxx.server"/>
    <property name="dataSource" ref="datasouce" />
    <property name="persistenceUnitName" value="pun" />
    <property name="jpaVendorAdapter" ref="JPAVendorAdapter" />
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.connection.release_mode" value="on_close" />
            <entry key="hibernate.transaction.jta.platform" value="com.xxx.server.JtaPlatformAdapter" />
        </map>
    </property>
</bean>

persistence.xml

<persistence-unit name="pun" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

服务

@Transactional
@Scope("prototype")
public synchronized void save(EntityObj model) throws Exception {
    model.setX(30);
    model.setY(40);

    EntityObj oldModel = entityObjDAO.findById(model.getId());
    // after call findById, the model had been commit to DB
    ...
    ...
    ...

    entityObjDAO.store(model); // this will call entityManager.merge(model)
    entityObjDAO.flush();
}

@Transactional
public EntityObj findById(String id) {
    EntityObj model = null;
    String sql = "select id,x,y from EntityObj where id = :id"; // this is a native sql query

    Query query = this.entityManager.createNativeQuery(sql);
    query.setParameter("id", id);
    Object[] rs = (Object[]) query.getSingleResult();
    if (rs != null) {
      model = new EntityObj();
      model.setId(id);
      model.setX(rs[1] == null ? null : (Integer) rs[1]);
      model.setY(rs[2] == null ? null : (Integer) rs[2]);
    }

  return model;
}

谢谢!

【问题讨论】:

  • 请更多信息,更多代码:)
  • @dit 我添加了 Service 和 DAO 的代码。谢谢。
  • 好的,到底是什么问题?
  • 当dao执行原生sql查询时,事务将被提交。但我需要旧对象与新对象进行比较。在 Hibernate 4.2 升级到 5.1 之前,查询执行时事务不会自动提交。 Spring、Hibernate 或 Atomikos 中的任何配置错误? PS.我的英语很基础,请不要介意。

标签: spring hibernate jpa spring-transactions atomikos


【解决方案1】:

如果您在代码中使用@Transactional,Spring 会为您的 Dao 对象(包装器)创建一个代理对象。

所以如果你的应用程序正在运行,它看起来像这样:

public EntityObj proxyMethodForFindById(String id) {

    try {
        // 1. start transaction
        startTransaction();

        // 2. execute your code
        return yourDaoObject.findById(id);

    } finally { // [!] PSEUDO CODE: NO EXCEPTION HANDLING

        // commit transaction
        commitTransaction();
    }

}

那么你的代码会发生什么?

您的保存方法也标记为@Transactional。因此,如果您通过设置更改对象:

model.setX(30);
model.setY(40);

Spring 创建了两个代理。一个给Service,四个你的Dao。在findById-Transaction 结束时,将提交此更改。嵌套事务是关键字。

您应该在您的findById-Method 中删除@Transaction,或者在整个 Dao 对象中更好。 Service 应该是事务性的,而不是道层的。

【讨论】:

  • 感谢您的回答!我从方法和类中删除了@Transactional,但在执行查询后事务仍然提交。
  • @T.SET 是的,这是因为您得到了相同的“触摸”对象。所以它可能不是提交,这只是您在上面所做的更改。
猜你喜欢
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多