【问题标题】:Spring 3.1 Hibernate 4 not rolling back JDBC transactionSpring 3.1 Hibernate 4 不回滚 JDBC 事务
【发布时间】:2012-12-17 22:21:12
【问题描述】:

我在设置将回滚的 JUnit 测试时遇到问题。在决定写一个问题之前,我已经阅读了一些关于 SO 的这些帖子,因为似乎没有一个是我问题的答案。

第二个测试用例失败,因为数据从第一个测试用例插入并保存在数据库中。

这是 JUnit 测试:

package com.company.group.spring.dao;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;

import com.company.group.spring.model.BusObj;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:NAME_OF_CONFIG_FILE.xml"})
@Transactional
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@TestExecutionListeners({TransactionalTestExecutionListener.class,
    DependencyInjectionTestExecutionListener.class}) 
public class PerPartsWCDAOTest {

    @Autowired
    @Qualifier("myBusObjDAO")
    private BusObjDAO busObj_dao;

    @Transactional
    @Test
    public void testInsertRollback() {
        try {
        BusObj busObj = new BusObj("some data...");

        assertNotNull(busObj_dao);
        assertNotNull(busObj);

        busObj_dao.insert(perPartWC);
        }
        catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    @Transactional
    @Rollback(false)
    @Test
    public void testInsert() {
        BusObj busObj2 = new BusObj("some data...");

        busObj_dao.insert(perPartWC2);
    }

}

这是 DAOImpl 类(我要测试的类):

package com.company.group.spring.dao;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.company.group.spring.model.BusObj;

@Repository("myBusObjDAO")
public class myBusObjDAOImpl implements myBusObjDAO {

private NamedParameterJdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource(DataSource dataSource) {
    this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

@Override
public void insert(BusObj someObj) {
    String sql = "insert into TABLE (args...) " +
            "VALUES (:named_params....)";

    SqlParameterSource paramSource = new BeanPropertySqlParameterSource(someObj);

    jdbcTemplate.update(sql, paramSource);
}

}

部分相关配置:

  <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />


  <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
      <property name="url" value="jdbc:oracle:thin:@SERVER:PORT:DB"/>
      <property name="username" value="USER"/>
      <property name="password" value="XXXXXX"/>

  </bean>

编辑:+调试打印

2012-12-18 08:50:42,177 [main] DEBUG [org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction()] Creating new transaction with name [com.company.group.spring.service.MyClassService.create]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

2012-12-18 08:50:42,342 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin()] Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction

2012-12-18 08:50:42,344 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin()] Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]

2012-12-18 08:50:42,361 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin()] Exposing Hibernate transaction as JDBC transaction [org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler@128647a[valid=true]]

2012-12-18 08:50:42,390 [main] DEBUG [org.springframework.jdbc.core.JdbcTemplate.update()] Executing prepared SQL update

2012-12-18 08:50:42,391 [main] DEBUG [org.springframework.jdbc.core.JdbcTemplate.execute()] Executing prepared SQL statement [insert into TABLE (args...) VALUES (?, ?, SYSDATE,?, ?, SYSDATE, ?,?, ?)]

2012-12-18 08:50:42,391 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection()] Fetching JDBC Connection from DataSource

2012-12-18 08:50:42,657 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection()] Registering transaction synchronization for JDBC Connection

2012-12-18 08:50:42,671 [main] DEBUG [org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement()] SQL update affected 1 rows

2012-12-18 08:50:42,678 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection()] Returning JDBC Connection to DataSource

2012-12-18 08:50:42,688 [main] DEBUG [org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback()] Initiating transaction rollback

2012-12-18 08:50:42,688 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback()] Rolling back Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]

2012-12-18 08:50:42,693 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doCleanupAfterCompletion()] Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction

更新: 我在日志中注意到,它正在尝试回滚 Hibernate 事务(但这是 JDBC)。然后注意到“txManager”的类目前是org.springframework.orm.hibernate4.HibernateTransactionManager,所以我尝试了org.springframework.jdbc.datasource.DataSourceTransactionManager,回滚成功了。所以我认为我的问题更具体地说是我如何配置使用 Hibernate 和 JDBC...我仍然不知道出了什么问题。

【问题讨论】:

  • 这是相关的(我认为)调试日志......如果我遗漏了什么,请告诉我

标签: spring hibernate transactions rollback jdbctemplate


【解决方案1】:

您的 JUnit 和 DAO 类看起来不错。

问题可能是连接在事务回滚之前自动提交。您可以更改 dataSource bean 以包含 defaultAutoCommit 属性

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
      <property name="url" value="jdbc:oracle:thin:@SERVER:PORT:DB"/>
      <property name="username" value="USER"/>
      <property name="password" value="XXXXXX"/>
      <property name="defaultAutoCommit" value="false" /> 
</bean> 

如果这不起作用,您可以粘贴控制台日志吗?

【讨论】:

【解决方案2】:

我的问题的解决方案是为 HibernateTransactionManager 指定数据源。这是HibernateTransactionManager 上的文档。

所以我想在原帖中没有发布我如何定义txManager 是一个错误。

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

改为:

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

我还在 SessionFactory 定义中添加了&lt;property name="dataSource"&gt;&lt;ref local="dataSource"/&gt;&lt;/property&gt;,但如果我只是担心 JdbcTemplate,这似乎没有必要。如果 HQL 混合在那里,怀疑它是需要的。

这是调试打印工作时的样子。我看到的唯一区别是这条线 Returning JDBC Connection to DataSource 在启动回滚之前不存在

2012-12-19 08:14:29,455 [main] DEBUG [org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction()] Creating new transaction with name [com.company.group.spring.service.MyClassService.create]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''

2012-12-19 08:14:29,512 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin()] Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction

2012-12-19 08:14:29,514 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin()] Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]

2012-12-19 08:14:29,539 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin()] Exposing Hibernate transaction as JDBC transaction [org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler@1289e48[valid=true]]

2012-12-19 08:14:29,558 [main] DEBUG [com.company.group.spring.dao.MyClassDAOImpl.insert()] Session Factory is: org.hibernate.internal.SessionFactoryImpl@1285252

2012-12-19 08:14:29,569 [main] DEBUG [org.springframework.jdbc.core.JdbcTemplate.update()] Executing prepared SQL update

2012-12-19 08:14:29,570 [main] DEBUG [org.springframework.jdbc.core.JdbcTemplate.execute()] Executing prepared SQL statement [insert into MY_CLASS (COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8, COL9) VALUES (?, ?, SYSDATE,?, ?, SYSDATE, ?,?, ?)]

2012-12-19 08:14:29,608 [main] DEBUG [org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement()] SQL update affected 1 rows

2012-12-19 08:14:29,611 [main] DEBUG [org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback()] Initiating transaction rollback

2012-12-19 08:14:29,612 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback()] Rolling back Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]

2012-12-19 08:14:29,680 [main] DEBUG [org.springframework.orm.hibernate4.HibernateTransactionManager.doCleanupAfterCompletion()] Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多