Spring 3.1 Hibernate 4 不回滚 JDBC 事务

标签 spring hibernate transactions rollback jdbctemplate

我在设置将回滚的 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...我仍然不知道哪里出了问题。

最佳答案

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

问题可能是连接在事务回滚之前自动提交。您能否更改数据源 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> 

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

关于Spring 3.1 Hibernate 4 不回滚 JDBC 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13923212/

相关文章:

java - 如何使用 JSR 验证来验证 Spring 中的 Controller 方法参数?

hibernate - 如何从 grails 事务中获取 hql 查询?

java - Spring JPA @OneToMany 参数值[]与预期类型不匹配

spring - 执行 spring 事务时出错

java - 使用 Transaction with JDBI/IDBI/Dropwizard -- 回滚问题

spring - 与元素类型 "value"关联的属性 "property"的值不得包含 '<' 字符

使用 Active Directory 的 Spring Security 3.1

Spring Cache - 仅当 API 响应成功时才清除缓存

java - @AttributeOverride 不适用于 Hibernate 5

c# - 如何将其(参见下面的代码)转换为 C#?