使用SpringTest测试,默认情况事务是不会提交的

本文展示了如何在Spring框架中使用测试注解控制数据库事务,包括数据的添加和回滚操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-bean.xml"})
public class DictionaryMapperTest{
	
	@Autowired
	private DictionaryItemMapper dictionaryItemMapper;
	
	
	@Test
	public void add(){
		DictionaryItem dic = new DictionaryItem();
		dic.setDicCode("0013");
		dic.setDicName("测试");
		dic.setGroupCode("001");
		dictionaryItemMapper.save(dic);
	}	
}

经过查找发现: 在上面这段示例代码中,test方法中的测试数据不会真的提交数据库,他将在test方法执行完毕后进行回滚。

如果你希望控制测试代码的事务提交,可以通过一些annotation来完成。 比如改成下面这样

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-bean.xml"})
@TransactionConfiguration(transactionManager = "txMgr", defaultRollback = true)
public class DictionaryMapperTest{
	
	@Autowired
	private DictionaryItemMapper dictionaryItemMapper;
	
	
	@Test
	public void add(){
		DictionaryItem dic = new DictionaryItem();
		dic.setDicCode("0014");
		dic.setDicName("测试");
		dic.setGroupCode("001");
		dictionaryItemMapper.save(dic);
	}	
}

 参考:http://www.iteye.com/problems/100963

转载于:https://my.oschina.net/u/1425545/blog/421765

<think>好的,用户之前问过关于同一个类中两个@Transactional方法事务失效的问题,现在他们想知道如何在Java Spring的本地测试中让事务回滚。我需要结合之前的讨论来给出合适的解答。 首先,用户可能是在测试时遇到了事务没有回滚的情况,所以需要指导他们正确配置测试环境。记得Spring测试默认会回滚事务,但可能用户没有正确使用相关注解或配置。 接下来,我得考虑用户的使用场景。他们可能是在写单元测试或者集成测试,尤其是涉及数据库操作的部分。需要确保测试方法使用@Transactional,并且配置正确的测试环境,比如使用@SpringBootTest,同时可能需要引入测试依赖比如spring-boot-starter-test。 用户可能存在的深层需求是希望测试后的数据库状态被改变,所以回滚是关键。但有时候他们可能也希望某些测试回滚,这时候需要告诉如何控制回滚行为。 记得之前提到的动态代理机制,这里可能需要涉及,但需要提到测试中的事务管理机制。可能需要解释@Rollback注解的使用,以及如何通过@Commit来覆盖默认行为。 另外,用户可能在测试中手动抛出异常来触发回滚,或者使用TransactionTemplate来编程式管理事务。需要分情况说明,给出代码示例。 还要注意数据库配置,比如是否使用嵌入式数据库,或者配置为H2,避免影响真实数据。同时,检查数据库引擎是否支持事务,比如InnoDB。 可能的误区包括:没有正确使用注解,或者测试方法没有被Spring代理,导致事务生效。这时候需要提醒正确使用@SpringBootTest和@Transactional,并确保依赖正确。 最后,验证方法也很重要,比如检查事务是否激活,或者查看数据库数据变化。可能需要给出如何打印事务状态的方法,如使用TransactionSynchronizationManager。 总结回答的结构,先说明默认行为,再分解决方案,包括配置测试环境、使用注解、异常触发、编程式事务,以及注意事项和验证方法。确保步骤清晰,代码示例准确,并覆盖用户可能遇到的问题。</think>在 Java Spring 的本地测试中,**事务回滚**的配置是测试数据库操作时的核心需求。以下是确保事务回滚的完整方案: --- ### **一、默认行为与原理** Spring 测试框架默认会 **自动回滚事务**,但需满足以下条件: 1. 测试使用 `@SpringBootTest` 或 `@Transactional` 注解 2. 测试方法中 **未显式提交事务**(例如未使用 `@Commit` 注解) --- ### **二、强制回滚的 4 种方法** #### **方法 1:依赖默认回滚(推荐)** ```java @SpringBootTest @Transactional // 声明测试类参与事务 public class ServiceTest { @Test public void testInsertData() { // 执行数据库操作(INSERT/UPDATE/DELETE) // 测试结束后自动回滚 } } ``` **原理**: - 测试方法结束后,Spring 会回滚事务(无论是否抛出异常) - 数据库状态保持变 --- #### **方法 2:手动抛出异常触发回滚** ```java @Test @Transactional public void testRollbackByException() { try { service.updateData(); // 可能触发异常的操作 } catch (Exception e) { throw new RuntimeException("强制回滚"); // 抛出非检查型异常 } } ``` **关键点**: - 默认情况下,只有 `RuntimeException` 和 `Error` 会触发回滚 - 如需其他异常触发回滚,需在 `@Transactional` 中添加配置: ```java @Transactional(rollbackFor = Exception.class) // 所有异常都触发回滚 ``` --- #### **方法 3:使用 `@Rollback` 注解(显式控制)** ```java @SpringBootTest public class ServiceTest { @Test @Transactional @Rollback // 强制回滚(默认值,可省略) public void testWithExplicitRollback() { // 执行数据库操作 } @Test @Transactional @Commit // 覆盖默认行为,强制提交 public void testWithCommit() { // 数据将持久化到数据库 } } ``` --- #### **方法 4:编程式事务管理(精细控制)** ```java @Autowired private TransactionTemplate transactionTemplate; @Test public void testProgrammaticRollback() { transactionTemplate.execute(status -> { try { // 执行数据库操作 return null; } catch (Exception e) { status.setRollbackOnly(); // 手动标记回滚 return null; } }); } ``` --- ### **三、验证事务是否回滚** #### **1. 打印事务状态** ```java import org.springframework.transaction.support.TransactionSynchronizationManager; @Test @Transactional public void testTransactionActive() { System.out.println("事务是否激活: " + TransactionSynchronizationManager.isActualTransactionActive()); System.out.println("是否只读事务: " + TransactionSynchronizationManager.isCurrentTransactionReadOnly()); } ``` #### **2. 检查数据库记录** ```java @Autowired private DataSource dataSource; @Test @Transactional public void testInsertRollback() throws SQLException { // 执行 INSERT 操作 try (Connection conn = dataSource.getConnection()) { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM table"); rs.next(); System.out.println("测试中记录数: " + rs.getInt(1)); // 事务内可见 } // 测试结束后,查询数据库确认无新增记录 } ``` --- ### **四、常见问题排查** | 问题现象 | 原因分析 | 解决方案 | |---------------------------|--------------------------|-----------------------------------| | 事务未回滚 | 使用了 `@Commit` 注解 | 移除 `@Commit` 注解 | | 回滚未生效 | 数据库引擎支持事务 | 检查是否使用 InnoDB(MySQL) | | 异常未触发回滚 | 异常类型在 `rollbackFor` 范围内 | 修改 `@Transactional(rollbackFor = Exception.class)` | | 测试类未加载事务管理器 | 缺少 `@Transactional` 或 `@SpringBootTest` | 添加必要的注解 | --- ### **五、最佳实践** 1. **测试配置**:在 `src/test/resources/application.properties` 中配置专用测试数据库 ```properties spring.datasource.url=jdbc:h2:mem:testdb spring.jpa.hibernate.ddl-auto=update ``` 2. **清理数据**:结合 `@Sql` 注解在测试前后重置数据库 ```java @Test @Sql(scripts = "/cleanup.sql", executionPhase = AFTER_TEST_METHOD) public void testWithCleanup() { ... } ``` 3. **事务传播行为**:需要多事务协作时,明确配置传播属性 ```java @Transactional(propagation = Propagation.NOT_SUPPORTED) // 挂起当前事务 ``` 通过以上配置,可确保测试既验证了业务逻辑,又不会污染数据库环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值