10.1 注解式事务
注解式事务把事务边界放在方法或类上,业务代码里不需要手动写 begin、commit、rollBack。这是 Service 层最常用的事务写法。
适合
- 一个业务方法天然就是一个事务边界。
- 希望异常时自动回滚,正常返回时自动提交。
- 项目已经使用 Spring、Solon 、Guice、Hasor,或者愿意用
TransactionHelper.support()创建代理对象。
不适合
- 方法不是通过代理对象调用。
- 同一个方法里需要根据运行时条件动态开启多个事务。
- 想手动控制某个
TransactionStatus的提交或回滚顺序。
基本用法
OrderService.java
import net.hasor.dbvisitor.jdbc.JdbcTemplate;
import net.hasor.dbvisitor.transaction.Transactional;
public class OrderService {
private final JdbcTemplate jdbcTemplate;
public OrderService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Transactional
public void createOrder(long orderId, long skuId) throws java.sql.SQLException {
jdbcTemplate.executeUpdate(
"insert into orders(id) values(?)",
orderId
);
jdbcTemplate.executeUpdate(
"insert into order_item(order_id, sku_id) values(?, ?)",
new Object[] { orderId, skuId }
);
}
}
执行效果:
createOrder正常返回时,两个insert一起提交。- 任意 SQL 抛出异常时,事务被标记为回滚,两个
insert都不会提交。
启用注解事务
@Transactional 本身只是标记,必须通过拦截器或代理对象调用才会生效。
普通 Java 程序
通过 TransactionHelper.support 创建代理对象
import javax.sql.DataSource;
import net.hasor.dbvisitor.jdbc.JdbcTemplate;
import net.hasor.dbvisitor.transaction.support.TransactionHelper;
DataSource dataSource = ...;
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
OrderService target = new OrderService(jdbcTemplate);
OrderService orderService = TransactionHelper.support(target, dataSource);
orderService.createOrder(10001L, 20001L);
TransactionHelper.support(target, dataSource) 会为 target 创建代理对象。只有调用代理对象上的方法时,@Transactional 才会触发事务拦截。
提示
不要在类内部用 this.createOrder(...) 期待触发事务;这种自调用不会经过代理对象。
这里使用的是 dbVisitor 自身的 @Transactional。Spring 项目使用 Spring 事务注解及管理器时,应遵循 Spring 的回滚规则,不要混用两套注解。
框架项目
- Spring 项目可以直接使用 Spring 的事务体系,查看 Spring 集成。
- Solon 项目可以通过 Solon 集成启用事务,查看 Solon 集成。
- Guice 和 Hasor 项目可以注入 dbVisitor 提供的事务对象,查看 Guice 集成、查看 Hasor 集成。