文章目录
事务管理配置
使用Spring提供的事务管理切面类 完成DAO中增删改操作的事务管理
1.1 事务的隔离级别
isolation 设置事务隔离级别: READ_UNCOMMITTED ,READ_COMMITTED , REPEATABLE_READ
, SERIALIZABLE
串行化:T1在执行的过程中,T2既不能读也不能写
可重复读:T1在执行的过程中,T2只能能读但不能改,T2可以添加数据(幻读)
读已提交:T1在执行的过程中,T2可以读也可以写,但是T1只能读取到T2提交后的数据(不可重复读)(幻读)
读未提交:T1在执行的过程中,T2可以读也可以写,T1可以读取到T2未提交的数据(脏读)(不可重复读)(幻读)
1.2 事务的传播机制
propagation 设置事务的传播机制
名称 | 说明 |
---|---|
PROPAGATION_REQUIRED | 默认的 ,如果当前没有事务,就新建一个事务;如果当前已经存在一个事务,就加入 |
PROPAGATION_SUPPORTS | 如果当前有事务,则使用当前事务;如果当前没有事务,就以非事务方法执行 |
PROPAGATION_MANDATORY | 如果当前有事务,则使用当前事务;如果当前没有事务,就抛出异常 |
PROPAGATION_REQUIRES_NEW | 无论当前有没有事务,就要创建一个新的事务;如果当前存在事务,就把当前的事务挂起(暂停) |
PROPAGATION_NOT_SUPPORTED | 无论当前有没有事务,都以非事务的方式执行;如果当前存在事务,就把当前的事务挂起(暂停) |
PROPAGATION_NEVER | 以非事务方式执行操作,如果存在事务,抛出异常 |
PROPAGATION_NESTED | 如果当前存在事务,则以子事务在嵌套事务内部执行;如果没有,就类似于 PROPAGATION_REQUIRED ,新建一个事务 |
@Service
public class StudentServiceTest {
@Autowired
private StudentService1 studentService1;
@Autowired
private StudentService2 studentService2;
@Transactional(propagation = Propagation.REQUIRED)
public void test(){
/**
* 1.验证手机号,作为用户名,拿到用户的密码 ==> 用户表 1
* 2.权限 跟插入用户表的操作返回的用户id
* 做一些权限列表的绑定 ==>插入到中间表(对用id==某一个权限)
* id userid permissionid
* 1 1 1
* 2 1 2
* 3 1 3
*/
studentService1.batchInsertCY();
throw new RuntimeException("无中生有的异常");
}
}
/**
* @author muzi@softeem.com
* @description @Transactional放在类上面,表示声明式事务的作用范围是该类中的
* 所有方法,默认使用REQUIRED传播行为
* @since 2021/4/13 20:28
*/
@Service
public class StudentService1 {
@Autowired
private StudentDao studentDao;
@Transactional(propagation = Propagation.REQUIRED)
public void batchInsertCY() {
try {
for (int i = 0; i < 10; i++) {
if (i == 5) {
throw new RuntimeException("无中生有的异常");
}
Student student = new Student();
student.setId(200 + i);
student.setName("陈禹" + i);
student.setAddress("东北三省" + i);
studentDao.insert(student);
}
} catch (Exception e) {
//捕捉异常,但是不再抛出,相当于内部消化了该异常
e.printStackTrace();
throw e;
}
}
}
1.3 编程式事务
<!-- Spring事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
@Repository
public class StudentDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private DataSourceTransactionManager transactionManager;
public void selectById(Integer id) {
String sql = "SELECT id,name FROM student WHERE id=?";
Student student = jdbcTemplate.queryForObject(sql, new Object[]{id}, new
BeanPropertyRowMapper<>(Student.class));
System.out.println(student);
}
public void batchInsert(List<Student> students){
String sql = "INSERT INTO student(id,name) VALUES(?,?)";
//创建事务
DefaultTransactionDefinition defaultTransactionDefinition = new
DefaultTransactionDefinition();
//开启事务
TransactionStatus status =
transactionManager.getTransaction(defaultTransactionDefinition);
try {
for (int i = 0; i < students.size(); i++) {
if (i == 4) {
throw new RuntimeException("无中生有的异常");
}
jdbcTemplate.update(sql, students.get(i).getId(),
students.get(i).getName());
}
//提交事务
transactionManager.commit(status);
} catch (Exception e) {
System.err.println("发生异常");
//回滚
transactionManager.rollback(status);
}
}
}
1.4 声明式事务
由于声明式事务是SpringAOP的典型实现,SpringAOP又依赖于AspectJ,所以一定要加入这个依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
1.4.1 Spring AOP事务管理配置—XML配置
<!--1.将Spring提供的事务管理配置配置给Spring容器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"/>
</bean>
<!--2.通过Spring jdbc提供的 tx标签,声明事务管理策略-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--3.将事务管理策略以AOP(切面切入点)配置 应用于DAO操作方法-->
<aop:config>
<aop:pointcut id="crud" expression="execution(* com.cg.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="crud"/>
</aop:config>
1.4.2 Spring AOP事务管理配置—注解配置
-
在applicationContext.xml中配置事务管理,声明使用注解方式进行事务配置
<!--使用注解进行事务管理前提是 IoC需要进行注解配置--> <context:annotation-config/> <context:component-scan base-package="com.cg"/> <!--1.将Spring提供的事务管理配置配置给Spring容器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="druidDataSource"/> </bean> <!--2.声明使用注解完成事务配置--> <tx:annotation-driven transaction-manager="transactionManager"/>
-
在需要Spring进行事务管理的方法上添加 @Transactional 注解
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.SUPPORTS ) public List<User> listUsers() { return userDAO.queryUsers(); }
@Transactional 可以用在 方法 上,代表给某个方法加上声明式事务,可以指定一些元配置信息,比如Propagation , isolation , timeout 和 readOnly ,建议加上 rollbackFor 属性,阿里规范
@Transactional也可以用在 类 上,达标给该类下所有的方法加入声明式事务
如果方法和类都有该注解,而且元配置信息不一致的情况下,遵循 就近原则