
事务是一个需要同时保证原子性、隔离性、一致性和持久性的一个或多个数据库 *** 作
本文会说明,springBoot中两种事务的实现方式,编程式事务配置和声明式事务配置还有切面事务,当然在此之前会说一些基础的东西:事务的四大特征,事务的隔离级别,事务的传播行为
事务的四大特征(ACID)- 原子性(Atomicity):事务中的全部 *** 作在数据库中是不可分割的,要么全部执行,要么均不执行.
- 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致.
- 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的.
- 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失.
@EnableTransactionManagementSpringBoot声明式事务
声明式事务@Transactional可以使用在类上,也可以使用在public方法上. 如果是使用在类上,则是对所有的public方法都开启事务,如果类和方法上都有则方法上的事务生效
可以在类上使用
@Transactional(rollbackFor=Exception.class)
public class TransactionServiceImpl implements TransactionService {
}
更多的是在方法上使用
@Override
@Transactional(rollbackFor=Exception.class)
public void t1(Student one) {
}
@Transactional的参数
在使用@Transactional的时候会用到它的一些参数
参数
作用
value
当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器.
transactionManager
当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器.
propagation
事务的传播行为,默认值为 Propagation.REQUIRED
isolation
事务的隔离级别,默认值为 Isolation.DEFAULT
timeout
事务的超时时间,默认值为-1.如果超过该时间限制但事务还没有完成,则自动回滚事务.
readOnly
指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置read-only为 true.
rollbackFor
用于指定能够触发事务回滚的异常类型,可以指定多个异常类型.
rollbackForClassName
用于指定能够触发事务回滚的异常类型,可以指定多个异常类型.
noRollbackFor
抛出指定的异常类型,不回滚事务,也可以指定多个异常类型.
noRollbackForClassName
抛出指定的异常类型,不回滚事务,也可以指定多个异常类型.
value和transactionManager相同 rollbackFor和rollbackForClassName相同 noRollbackFor和noRollbackForClassName相同
事务的隔离级别(isolation)isolation中会用到隔离级别
参数
事务隔离级别
脏读
不可重复读
幻读
READ_UNCOMMITTED
读未提交(read-uncommitted)
是
是
是
READ_COMMITTED
不可重复读(read-committed)
否
是
是
REPEATABLE_READ
可重复读(repeatable-read)
否
否
是
SERIALIZABLE
串行化(serializable)
否
否
否
propagation会用到这个传播行文
传播行为
解释
REQUIRED
如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务.
SUPPORTS
如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行.
MANDATORY
如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常.
REQUIRES_NEW
重新创建一个新的事务,如果当前存在事务,暂停当前的事务.
NOT_SUPPORTED
以非事务的方式运行,如果当前存在事务,暂停当前的事务.
NEVER
以非事务的方式运行,如果当前存在事务,则抛出异常.
NESTED
和REQUIRED效果一样.
在需要的地方注入TransactionTemplate
@Autowired private TransactionTemplate transactionTemplate;
然后在代码中使用
@Override
public final void save2() {
transactionTemplate.execute((status)->{
mapper.saveStudent(newOne());
mapper.saveStudent(newOne());
return Boolean.TRUE;
});
}
这样两个mapper.saveStudent(newOne());就在一个事务中执行了
SpringBoo切面编程式事务此种方式基于AOP功能,所以需要添加
org.springframework.boot spring-boot-starter-aop
写配置类
@Aspect
@Configuration
public class MyTransactionConfig {
private final static int TX_METHOD_TIME_OUT = 10;
private static final String POITCUT_expression = "execution(* zdc.enterprise.service.impl.*.*(..))";
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Bean
public TransactionInterceptor txadvice() {
RulebasedTransactionAttribute readonlyRule = new RulebasedTransactionAttribute();
readOnlyRule.setReadonly(true);
readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
RulebasedTransactionAttribute requireRule = new RulebasedTransactionAttribute();
requireRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
requireRule.setTimeout(TX_METHOD_TIME_OUT);
Map nameMap = new HashMap<>();
nameMap.put("add*", requireRule);
nameMap.put("save*", requireRule);
nameMap.put("insert*", requireRule);
nameMap.put("update*", requireRule);
nameMap.put("delete*", requireRule);
nameMap.put("remove*", requireRule);
nameMap.put("batch*", requireRule);
nameMap.put("get*", readOnlyRule);
nameMap.put("query*", readOnlyRule);
nameMap.put("find*", readOnlyRule);
nameMap.put("select*", readOnlyRule);
nameMap.put("count*", readOnlyRule);
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.setNameMap(nameMap);
TransactionInterceptor transactionInterceptor = new TransactionInterceptor(platformTransactionManager, source);
return transactionInterceptor;
}
@Bean
public Advisor txAdviceAdvisor() {
AspectJexpressionPointcut pointcut = new AspectJexpressionPointcut();
pointcut.setexpression(POITCUT_expression);
return new DefaultPointcutAdvisor(pointcut, txadvice());
}
}
有了这个切面配置类,就不要用在类或者每个方法上使用@Transactional了,当然方法名前缀要能和设置的匹配上.
RulebasedTransactionAttribute的参数大致和@Transactional的参数相同,里面有详细的注释,就不过多解释了
切面事务粒度最粗,如果方法名不匹配容易漏方法,声明式事务粒度中等,但是遇到大事务就会出现问题,编程式事务粒度最细,可以考虑在特殊的时候使用它
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)