spring 事务
2022-04-22 16:02:59 0 举报
AI智能生成
spring 事务
作者其他创作
大纲/内容
事务
属性
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
隔离级别
Read uncommitted(未授权读取、读未提交)
Read committed(授权读取、读提交)
Repeatable read(可重复读取)【mysq默认】
Serializable(序列化)
事务的死锁
事务A和事务B在操作同一条记录
事务执行时间过长
代码例子
事务管理机制
编程式事务
基于底层的API,如PlatformTransactionManager、
TransactionDefinition 和 TransactionTemplate
TransactionDefinition 和 TransactionTemplate
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 事务操作
// 事务提交
transactionManager.commit(status);
} catch (DataAccessException e) {
// 事务提交
transactionManager.rollback(status);
throw e;
}
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 事务操作
// 事务提交
transactionManager.commit(status);
} catch (DataAccessException e) {
// 事务提交
transactionManager.rollback(status);
throw e;
}
编程式事务方式需要是开发者在代码
中手动的管理事务的开启、提交、回滚等操作
中手动的管理事务的开启、提交、回滚等操作
声明式事务
声明式事务管理方法允许开发者配置的帮助下来管理事务,
而不需要依赖底层API进行硬编码。开发者可以只使用注解或基于配置的 XML 来管理事务。
而不需要依赖底层API进行硬编码。开发者可以只使用注解或基于配置的 XML 来管理事务。
@Transactional
事务的传播
REQUIRED
Spring默认的事务传播类型
如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务
如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务
SUPPORTS
当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
MANDATORY
当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
REQUIRES_NEW
创建一个新事务,如果存在当前事务,则挂起该事务。
NOT_SUPPORTED
始终以非事务方式执行,如果当前存在事务,则挂起当前事务
NEVER
不使用事务,如果当前事务存在,则抛出异常
NESTED
如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)
优点
对代码没有侵入性,方法内只需要写业务逻辑就可以了。
缺点
如果开发者没有注意到一个方法是被事务嵌套的,那么就
可能会再方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作
可能会再方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作
这些操作自身是无法回滚的,这就会导致数据的不一致。
可能RPC调用成功了,但是本地事务回滚了,可是PRC调用无法回滚了。
可能RPC调用成功了,但是本地事务回滚了,可是PRC调用无法回滚了。
在事务中有远程调用,就会拉长整个事务。那么久会导致本事务的数据库
连接一直被占用,那么如果类似操作过多,就会导致数据库连接池耗尽。
连接一直被占用,那么如果类似操作过多,就会导致数据库连接池耗尽。
声明式事务用不对容易失效
@Transactional 应用在非 public,final修饰的方法上
@Transactional 注解属性 propagation 设置错误
@Transactional 注解属性 rollbackFor 设置错误
同一个类中方法调用,导致@Transactional失效
错误例子
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void add(UserModel userModel) {
userMapper.insertUser(userModel);
updateStatus(userModel);
}
@Transactional
public void updateStatus(UserModel userModel) {
doSameThing();
}
}
public class UserService {
@Autowired
private UserMapper userMapper;
public void add(UserModel userModel) {
userMapper.insertUser(userModel);
updateStatus(userModel);
}
@Transactional
public void updateStatus(UserModel userModel) {
doSameThing();
}
}
解决1:只需要新加一个Service方法,把@Transactional注解加到新Service方法上
解决2:Service类中注入自己
解决3:
@Servcie
public class ServiceA {
public void save(User user) {
queryData1();
queryData2();
((ServiceA)AopContext.currentProxy()).doSave(user);
}
@Transactional(rollbackFor=Exception.class)
public void doSave(User user) {
addData1();
updateData2();
}
}
public class ServiceA {
public void save(User user) {
queryData1();
queryData2();
((ServiceA)AopContext.currentProxy()).doSave(user);
}
@Transactional(rollbackFor=Exception.class)
public void doSave(User user) {
addData1();
updateData2();
}
}
异常被catch捕获导致@Transactional失效
因为spring事务,默认情况下只会回滚RuntimeException(运行时异常)和Error(错误),
对于普通的Exception(非运行时异常),它不会回滚。
对于普通的Exception(非运行时异常),它不会回滚。
数据库引擎不支持事务
(类本身) 未被spring管理
多线程调用
@Slf4j
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleService roleService;
@Transactional
public void add(UserModel userModel) throws Exception {
userMapper.insertUser(userModel);
new Thread(() -> {
roleService.doOtherThing();
}).start();
}
}
@Service
public class RoleService {
@Transactional
public void doOtherThing() {
System.out.println("保存role表数据");
}
}
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleService roleService;
@Transactional
public void add(UserModel userModel) throws Exception {
userMapper.insertUser(userModel);
new Thread(() -> {
roleService.doOtherThing();
}).start();
}
}
@Service
public class RoleService {
@Transactional
public void doOtherThing() {
System.out.println("保存role表数据");
}
}
0 条评论
下一页