Spring 中的事务处理
JDBC 中的事务处理
1、代码片段,模拟一段代码修改一份数据
@Test
public void test_jdbc_transaction() throws SQLException, ClassNotFoundException {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");//MySQL5以后可直接省略
//获取数据库连接
Connection con = null;
try {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/project?serverTimezone=GMT%2B8&useSSL=false","root","zcq200427");
con.setAutoCommit(false);
//获取执行者对象
Statement stat = con.createStatement();
//执行sql语句并返回结果
String sql = "update user set name = 'cccc' where id = 1";
int flag = stat.executeUpdate(sql);
int i = 1 / 0;
// //处理结果
// while (re.next()){
// System.out.println(re.getLong("id")+"\t"+re.getString("name")+"\t" );
// }
}catch (Exception e) {
// if (con != null) {
// con.rollback();
// }
e.printStackTrace();
}
finally {
if (con != null) {
con.setAutoCommit(true);
con.close();
}
}
}
1、首先由于数据库默认采用的是自动提交事务,所以需要先吧默认设置改为
FALSE
con.setAutoCommit(false);
2、手动模拟一个异常int i = 1 / 0;
算术异常
3、捕获异常,随后进行事务回滚
4、查看数据库情况
当我们不进行数据库回滚时,我们发现这条更改的数据依然下沉到了我们的数据库当中,显然这是不正确的。
所以需要我们在捕获异常后手动进行数据库事务回滚
SpringBoot 中的事务处理
1、在启动类上添加
@EnableTransactionManagement
注解,当然不加也行因为在spring,factoris
有默認的配置
2、在對應的service
方法上添加@Transactional
注解,如果在service
類上添加注解就代表該service
的所有PUBLIC
类上都开启事务特性 (建议在事务方法上开启事务特性添加@Transactional
)
@Transactional
Propagation propagation() default Propagation.REQUIRED;
事务默认的传播行为
Isolation isolation() default Isolation.DEFAULT;
事务默认的隔离级别
注意事项:
1、不能在非 public 方法上使用 @Transactional
否则会不生效
2、当在同一个 service
类中调用另一个事务方法时,不能直接调用,必须使用他的 bean 进行调用
@Override
//@Transactional(propagation = Propagation.REQUIRED , isolation = Isolation.DEFAULT , rollbackFor = Exception.class)
@Transactional
public Boolean updateByPrimaryKey(long id) {
Preconditions.checkArgument(id >= 0 , "id 必须大于 0 且 不等于 0 ");
userService.test();
return Boolean.FALSE;
}
@Transactional
public void test() {
LambdaUpdateWrapper<User> eq =
Wrappers.lambdaUpdate(User.class).eq( User::getId, 1)
.set(User::getName , "11111");
int updateFlag = userMapper.update(null , eq);
int i = 1 / 0;
}
3、因为 spring 处理事务默认是使用的动态代理的方式,所以必须使用 spring 的代理类