使用了@Transaction注解依然报TransactionRequireException异常

本文解析了在Spring框架中,@Transaction注解与@PostConstruct注解同时使用导致事务失效的问题,并提供了解决方案。通过使用JdbcTemplate直接执行SQL更新语句,避免了手动事务控制,同时强调了在方法间调用时如何确保事务正确执行。

使用了@Transaction注解依然报TransactionRequireException异常

今天启动项目的时候失败,报了TransactionRequireException异常,而此异常的产生原因在我印象中是由于进行了增删改操作,而未配置事务造成的,于是找到出错行,发现有@Transaction注解,即应该是配置了事务的,不解下上网一顿百度,找到了原因,是同时使用了@PostConstruct注解和@Transaction注解造成的,二者同时使用会造成@Transaction注解失效。代码如下。
在这里插入图片描述
解决方式:将增删改语句修改为:

@Autowired
private JdbcTemplate jdbcTemplate;
private static String sql = "UPDATE jy_scheduler set task_state = '0' WHERE id = ?";
……
this.jdbcTemplate.update(sql, taskSchedule.getId());

如上,直接使用JdbcTemplae去执行修改语句就可以了,由于是单条sql语句,所以不用去手动控制它的事务。

画重点的地方来了,当你的使用了@Transaction注解的方法是被同类方法调用,事务是不会生效的,这是代理机制的原因,
可以使用本类代理对象去调用来解决这个问题,详情请见博主的这篇博文https://blog.csdn.net/weixin_41644977/article/details/88747159

### Spring @Transactional 注解 使用指南与常见问题 #### 1. @Transactional 注解的基本使用 @Transactional 注解是 Spring 框架中用于声明式事务管理的核心注解。它可以通过简单的配置实现对方法的事务控制,而无需编写复杂的事务管理代码。该注解可以应用于类或方法级别[^2]。 - **类级别**:当 @Transactional 应用于类时,类中的所有公共方法都将被事务管理。 - **方法级别**:推荐在方法上使用 @Transactional,以实现更细粒度的事务控制。 ```java @Service public class OrderService { @Transactional public void createOrder() { // 业务逻辑 } } ``` #### 2. 注意点:@Transactional 只能作用于公共方法 @Transactional 注解只能作用于公共方法。如果将该注解应用于私有或受保护的方法,则 Spring AOP 无法检测到这些注解,从而导致事务不起作用[^2]。 ```java // 错误示例:私有方法上的 @Transactional 不起作用 private @Transactional void updateAccount() { // 更新账户逻辑 } ``` #### 3. 自调用问题及其解决方案 在同一类中,如果一个非事务方法调用了带有 @Transactional 注解的另一个方法,事务将不会生效。这是因为 Spring AOP 使用代理机制,只有通过代理对象调用的方法才会被事务管理[^3]。 **解决方法**: - 使用 AspectJ 取代 Spring AOP 代理,以解决自调用问题[^1]。 - 或者通过显式注入当前 Bean 的代理实例来调用目标方法。 ```java @Service public class OrderService { @Autowired private OrderService self; private void insert() { self.insertOrder(); // 通过代理对象调用 } @Transactional public void insertOrder() { // 插入订单逻辑 } } ``` #### 4. 事务边界的问题 Spring AOP 在事务管理中仅检查首次进入 @Autowired 代码时的注解状态。如果一个未标注 @Transactional 的方法调用了另一个标注了 @Transactional 的方法,后者将被忽略[^2]。 ```java // 错误示例:事务边界未正确创建 public void processOrder() { saveOrder(); // 此处没有事务 } @Transactional public void saveOrder() { // 保存订单逻辑 } ``` #### 5. 编程式事务管理:TransactionTemplate 对于需要动态或复杂事务逻辑的场景,可以使用 TransactionTemplate 进行编程式事务管理[^4]。 - **execute 方法**:执行包含事务的代码块,并支持返回值。 - **executeWithoutResult 方法**:执行无返回值的事务操作。 ```java @Autowired private TransactionTemplate transactionTemplate; public User createUser(User user) { return transactionTemplate.execute(status -> { try { User newUser = userDao.save(user); return newUser; } catch (DataAccessException e) { status.setRollbackOnly(); throw new ServiceException("保存用户失败", e); } }); } ``` #### 6. DAO 层事务管理 在 DAO 层使用 @Transactional 注解时,通常需要抛出异常以触发事务回滚。例如,在 BaseDaoImpl 中,save、update 和 delete 方法均可能抛出 Exception[^5]。 ```java @Transactional public Object save(Object entity) throws Exception { getSession().save(entity); return entity; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值