事务
事务的概念和简单使用
1.什么是声明式事务?
以方法为单位,进行事务控制;抛出异常,事务回滚,最小的执行单位为方法,决定执行成败是通过是否抛出异常来判断的,抛出异常即执行失败
- Spring的声明事务实现
[1]事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编码式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;
声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。
声明式事务有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于@Transactional 注解的方式,下面我们是针对注解的使用进行讲解
@Transactional:事务注解,对我们的实例类进行事务声明
它可以加到类上,也可以加到方法上,加到类上时,对类上的所有公有方法生效。如果类上也有,方法上也有,方法上的属性会覆盖类上的。
加到service的实现类上。
@EnableTransactionManagement 事务管理注解,开启事务管理器,对声明了@Transactional的类进行管理
1主启动类上加@EnableTransactionManagement 开启事务管理
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
@EnableTransactionManagement
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2 service的实现类上加transactional 注解,并在其中模拟产生异常,看是否回滚
package com.example.demo.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.domain.Person;
import com.example.demo.domain.Population;
import com.example.demo.domain.ResultMsg;
import com.example.demo.mapper.PersonMapper;
import com.example.demo.mapper.PopulationMapper;
@Service
@Transactional(rollbackFor={RuntimeException.class,Exception.class})
public class PopulationServiceImpl implements IPopulationService {
@Resource
PopulationMapper populationMapper;
@Resource
PersonMapper personMapper;
@Override
@Transactional
public ResultMsg save(Person person, Population population) {
ResultMsg rm=new ResultMsg();
//补全户主名称
population.setHouseHolder(person.getName());
//存户口信息
int count=populationMapper.insert(population);
//模拟产生异常,看是否回滚
int i=0;
int y=2/i;
if(count>0){
//户口存储成功,获取户号
String popid=population.getId();
//设置人员户号
person.setPopulationId(popid);
int count2=personMapper.insert(person);
if(count2>0){
rm=new ResultMsg(0,"成功");
}else{
rm=new ResultMsg(-1,"人员信息失败");
}
}else{
rm=new ResultMsg(-1,"户口信息存储失败");
}
return rm;
}
}
事务的传播行为
事务传播行为
@Transactional 注解中的 propagation 属性,可以设置事务传播行为。属性值为:
-
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,就加入到这个事务中。这是最常见的选择。
-
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
-
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
-
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
-
NOT_SUPPORTED:以非事务方式执行操作,如果存在事务,就把当前事务挂起。
-
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
-
NESTED:嵌套事务执行,如果没有事务就按REQUIRED来执行,也就是新建一个事务
它能让事务部分回滚@Transactional(propagation=Propagation.REQUIRED)
public ResultMsg save(Person person, Population population) {
.......
}
1、用NESTED
https://www.cnblogs.com/yifanSJ/p/16330741.html
事务A 中包含B事务(批量插入时(事物A) 会调用单个插入操作(事务b)),
如果B失败了,只会回滚B,a会被提交
a->执行B之前设置了savepoint
2、如果用REQUIRED,如果B失败了,ab都回滚