【发布时间】:2018-10-09 01:35:02
【问题描述】:
@RestController
@RequestMapping("/Api/Order")
public class OrderController {
private OrderService service;
private RefundService refundService;
@AsCustomer
@DeleteMapping(value = "/{orderID}/RefundApplication")
@Transactional(rollbackFor = RuntimeException.class)
public Map cancelRefundApplication(@SessionAttribute("user") User user,
@PathVariable("orderID") String orderID) {
Order order = service.getOrderByID(orderID);
RefundApplication application = refundService.get(orderID);
order.setState(Order.STATE_PAYED);
refundService.delete(orderID);
service.updateOrder(order);
throw new EntityNotFoundException("test");
}
...
我希望在cancelRefundApplication 方法中创建的事务在抛出 RuntimeException 时回滚,如果没有抛出 RuntimeException 则提交。但我发现即使抛出 RuntimeException 事务也不会回滚。对于测试目的,我更改了代码以使其始终抛出 EntityNotFoundException,并使用以下测试方法对其进行测试。运行测试后查看数据库,发现退款申请数据被删除,说明事务没有回滚,@Transactional注解不起作用。
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {WebConfig.class, RootConfig.class, DataConfig.class})
@WebAppConfiguration
class OrderControllerTest {
@Autowired
OrderController controller;
@Autowired
UserService userService;
@Autowired
OrderService orderService;
@Autowired
AppWideExceptionHandler exceptionHandler;
private User customer;
private User seller;
private HashMap<String, Object> sessionAttrs;
private ResultMatcher success = jsonPath("$.code")
.value("0");
private MockMvc mockMvc;
@Test
void cancelRefundApplication() throws Exception {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
String path = String.format("/Api/Order/%s%d0001/RefundApplication"
, simpleDateFormat.format(new Date()), customer.getID());
mockMvc.perform(delete(path)
.characterEncoding("UTF-8")
.sessionAttrs(sessionAttrs))
.andDo(print())
.andExpect(success);
}
...
这是 DataConfig 类:
@Configuration
@MapperScan("youshu.mapper")
public class DataConfig {
@Bean
public DataSource dataSource() {
// org.apache.ibatis.logging.LogFactory.useLog4J2Logging();
PooledDataSource pds = new PooledDataSource();
pds.setDriver("com.mysql.cj.jdbc.Driver");
pds.setUsername(...);
pds.setPassword(...);
pds.setUrl("jdbc:mysql://XXXX");
return pds;
}
@Bean
public JdbcOperations jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setTypeAliasesPackage("youshu.entity");
return sessionFactory.getObject();
}
@Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionTemplate sqlSession(SqlSessionFactory factory){
return new SqlSessionTemplate(factory);
}
}
【问题讨论】:
-
你需要在测试中添加
@Transactional注解,也可以提供properties文件和DataConfig.class -
@shahaf 如果我在测试方法中添加
@Transactional,即使没有抛出异常,它也会一直回滚,这不是我想要的。我已更新问题以提供 DataConfig 类。 -
我显然是想使用相同的注释
@Transactional(rollbackFor = RuntimeException.class),现在也更改您的数据库用户名和密码!! -
@shahaf 我发现我粘贴了错误的测试方法。我再次更新了问题。谢谢你提醒我。
-
您在哪里启用了交易?
标签: spring spring-mvc