【问题标题】:Spring @Transactional rollback not workingSpring @Transactional 回滚不起作用
【发布时间】: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


【解决方案1】:

事务需要通过使用@EnableTransactionManagement注释配置类来手动启用

【讨论】:

    【解决方案2】:

    检查是否在您的测试中包含TransactionalTestExecutionListener,如果没有添加:@TestExecutionListeners(listeners = {TransactionalTestExecutionListener.class})

    【讨论】:

      猜你喜欢
      • 2019-06-15
      • 2016-12-19
      • 2017-04-14
      • 2020-06-04
      • 1970-01-01
      • 2018-11-08
      • 2020-06-20
      • 2012-04-18
      相关资源
      最近更新 更多