软件设计之SSM(6)
路线图推荐:
【Java学习路线-极速版】【Java架构师技术图谱】
尚硅谷新版SSM框架全套视频教程,Spring6+SpringBoot3最新SSM企业级开发
资料可以去尚硅谷官网免费领取
学习内容:
- 声明式事务
- 基本事务控制步骤
1、声明式事务
编程式事务
是通过代码手动控制事务的开始、提交、回滚等操作,典型实现是使用TransactionManager或者Connection的API。声明式事务
是通过配置的方式来管理事务,通常使用注解或XML配置声明事务的边界。Spring框架提供了声明式事务的支持,最常用的是通过@Transactional注解。
区别 | 编程式事务 | 声明式事务 |
---|---|---|
控制方式 | 手动控制事务的开始、提交和回滚 | 通过配置或注解声明事务边界,自动管理 |
灵活性 | 灵活,适合复杂业务场景 | 适合常规的事务管理场景,易于使用 |
代码侵入性 | 高,事务管理逻辑与业务代码混合在一起 | 低,业务代码与事务管理逻辑解耦 |
配置复杂度 | 无需额外配置,但需编写大量事务管理代码 | 通过简单的配置或注解即可实现事务管理 |
错误处理 | 需要手动捕获异常并进行回滚操作 | Spring自动管理回滚操作,按需通过配置定制回滚规则 |
事务管理器
Spring 的事务管理器能够针对不同数据库提供事务管理的功能,主要是因为它采用了一种 抽象的事务管理机制
,并针对不同的数据库和持久化技术提供了多个实现类。
事务管理器 | 适用场景 | 主要应用技术 | 底层原理 |
---|---|---|---|
DataSourceTransactionManager | 关系型数据库(基于 JDBC) | JDBC | 基于 DataSource 管理数据库连接和事务 |
JpaTransactionManager | 基于 JPA 的持久化框架 | JPA | 基于 EntityManagerFactory 管理事务 |
HibernateTransactionManager | 使用 Hibernate 作为 ORM 框架 | Hibernate | 直接与 SessionFactory 和 Transaction 交互 |
JtaTransactionManager | 分布式事务、多个数据源或消息队列事务管理 | JTA(Java Transaction API) | 基于 JTA 的全局事务管理器 |
2、基本事务控制步骤
注意点:
@EnableTransactionManagement
表示开启事务支持
@Transactional
可以放在方法或类上,放方法
上:当前方法有事务;放在类
上:类下的所有方法都有事务
事务属性:只读
对一个查询操作来说,如果我们把它设置成只读
,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。
// readOnly = true把当前事务设置为只读 默认是false!
@Transactional(readOnly = true)
事务属性:超时时间
事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源
。而长时间占用资源,大概率是因为程序运行出现了问题(可能是Java程序或MySQL数据库或网络连接等等)。设置超时时间:超时回滚,释放资源
@Service
public class StudentService {
@Autowired
private StudentDao studentDao;
/**
* timeout设置事务超时时间,单位秒! 默认: -1 永不超时,不限制事务时间!
*/
@Transactional(readOnly = false,timeout = 3)
public void changeInfo(){
studentDao.updateAgeById(100,1);
//休眠4秒,等待方法超时!
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
studentDao.updateNameById("test1",1);
}
}
事务属性:事务异常
默认只针对运行时异常
回滚,编译时异常
不回滚
特征 | 编译时异常 | 运行时异常 |
---|---|---|
定义 | 编译时异常是编译器在编译时检查的异常,它必须被处理。 | 运行时异常是在程序运行时发生的异常,不必强制处理。 |
继承结构 | 编译时异常通常是 Exception 的子类,但不包括 RuntimeException 。 | 运行时异常是 RuntimeException 的子类。 |
处理方式 | 编译时异常必须通过 try-catch 块捕获或在方法签名中声明。 | 运行时异常可以选择处理,也可以不处理,通常不需要显式声明。 |
例子 | IOException , SQLException , ClassNotFoundException | NullPointerException , ArrayIndexOutOfBoundsException , ArithmeticException |
发生时机 | 在编译期间发生,程序无法编译通过。 | 在程序运行期间发生,可能会导致程序崩溃。 |
用户可控性 | 需要在代码中显式处理,因此开发者必须考虑并处理。 | 不需要显式处理,通常表示程序存在潜在的逻辑错误。 |
设置回滚异常
rollbackFor属性:
指定哪些异常类才会回滚,默认是 RuntimeException and Error 异常方可回滚!
/**
* timeout设置事务超时时间,单位秒! 默认: -1 永不超时,不限制事务时间!
* rollbackFor = 指定哪些异常才会回滚,默认是 RuntimeException and Error 异常方可回滚!
* noRollbackFor = 指定哪些异常不会回滚, 默认没有指定,如果指定,应该在rollbackFor的范围内!
*/
@Transactional(readOnly = false,timeout = 3,rollbackFor = Exception.class,noRollbackFor = FileNotFoundException.class)
事务属性:事务隔离级别
数据库事务的隔离级别是指在多个事务并发执行
时,数据库系统为了保证数据一致性所遵循的规定。常见的隔离级别包括:
@Transactional(isolation = Isolation.REPEATABLE_READ)
隔离级别 | 描述 | 可能出现的问题 | 解决方案 |
---|---|---|---|
READ UNCOMMITTED | 允许读取未提交的数据,隔离级别最低。 | 脏读(Dirty Read):读取到其他事务未提交的数据。 | 使用更高的隔离级别。 |
READ COMMITTED | 只允许读取已提交的数据,避免脏读。 | 非重复读(Non-repeatable Read):同一查询在同一事务中返回不同结果。 | 使用更高的隔离级别。 |
REPEATABLE READ | 确保在一个事务中多次读取相同数据时返回相同结果,避免脏读和非重复读。 | 幻读(Phantom Read):在同一事务中查询结果集的行数变化。 | 使用更高的隔离级别,或者采用锁机制。 |
SERIALIZABLE | 最高的隔离级别,强制事务串行执行,完全避免脏读、非重复读和幻读。 | 性能开销大,可能导致更高的等待时间和死锁。 | 根据需要评估是否使用此级别,优化事务逻辑。 |
事务属性:事务传播行为
事务传播行为(Transaction Propagation)是指在 Spring 框架中,当一个事务方法被另一个事务方法调用时,如何处理事务的传播和管理。不同的传播行为决定了新事务如何与当前事务相互作用。
注意:
在同一个类中,@Transactional 注解的方法调用不会生效,因为 Spring 使用代理模式实现事务管理。在同一个类内的方法调用直接引用对象,绕过了代理,因此事务传播行为不会被触发。
传播行为 | 描述 |
---|---|
PROPAGATION_REQUIRED | 默认传播行为。如果存在一个事务,则支持该事务;如果没有,则新建一个事务。[ 当前方法的事务会与外部(调用者)事务共享。 ] |
PROPAGATION_REQUIRES_NEW | 总是新建一个事务。如果存在一个事务,暂停当前事务,然后创建新的事务。 |