Spring事务抽象
Spring事务传播特性
Spring中通过Propagation来设置事务的传播属性的,在这个属性中提供了我们其中关于事务传播的特性:
- PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
默认
- PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。无论是否有事务,都起一个新的事务。两个事务没有关联。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。在当前事务内再起一个新事务。如果外部事务回滚,内嵌事务也会回滚。
Spring事务的隔离级别
Spring实现事务
1 编程式事务
@SpringBootApplication
@Slf4j
public class ProgrammaticTransactionDemo implements CommandLineRunner {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
public static void main(String[] args) {
SpringApplication.run(ProgrammaticTransactionDemo.class, args);
}
@Override
public void run(String... args) throws Exception {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'aaa')");
}
});
}
}
2 声明式事务
事务是通过 AOP(面向切面编程)实现的。当一个方法被声明为事务方法时,Spring 会在运行时为该方法创建一个代理对象,并在代理对象中添加事务管理的逻辑。当调用该方法时,实际上是调用代理对象的方法
,而不是原始对象的方法。
1.开启事务
@EnableTransactionManagement
2.在需要的方法或者类添加注解
@Transactional
举例
1 事务注解的方法
2 事务注解,指定了在什么异常会进行回滚
3 普通方法调用了一个有事务的方法
⚠️ 3并不会回滚,insert的数据会被插入进去
原因:如果一个普通方法调用一个有事务的方法,那么实际上是在调用原始对象的方法
,而不是代理对象的方法。因此,没有事务支持。
那么,普通方法该如果调用事务方法并实现事务支持呢?
通过依赖注入的方式调用有事务的方法:可以将有事务的方法封装在一个单独的组件中,并通过依赖注入的方式在普通方法中调用该组件。由于依赖注入是通过 Spring 容器实现的,因此调用的实际上是代理对象的方法,从而具有事务支持。
将有事务的方法封装在一个 Service 组件中:
@Service
@Transactional
public class MyService {
public void transactionalMethod() {
// ...
}
}
在普通方法中通过依赖注入的方式调用该组件:
@Service
public class MyOtherService {
@Autowired
private MyService myService;
public void myMethod() {
// 调用有事务的方法
myService.transactionalMethod();
}
}
MyOtherService 组件通过依赖注入的方式调用了 MyService 组件中的 transactionalMethod 方法,由于调用的是代理对象的方法,因此具有事务支持。