编程式事务与声明式事务
- 编程式事务
编程式事务是指手动编写程序来管理事务,即通过编写代码的方式直接控制事务的提交和回滚。在 Java 中,通常使用事务管理器(如 Spring 中的 PlatformTransactionManager
)来实现编程式事务。
编程式事务的主要优点是灵活性高,可以按照自己的需求来控制事务的粒度、模式等等。但是,编写大量的事务控制代码容易出现问题,对代码的可读性和可维护性有一定影响。
编程式的实现方式存在缺陷:
- 细节没有被屏蔽:具体操作过程中,所有细节都需要程序员自己来完成,比较繁琐。
- 代码复用性不高:如果没有有效抽取出来,每次实现功能都需要自己编写代码,代码就没有得到复用。
- 声明式事务
声明式事务是指使用注解或 XML 配置的方式来控制事务的提交和回滚。
开发者只需要添加配置即可, 具体事务的实现由第三方框架实现,避免直接进行事务操作。
使用声明式事务可以将事务的控制和业务逻辑分离开来,提高代码的可读性和可维护性。
- Spring事务管理器
依赖:
- spring-tx: 包含声明式事务实现的基本规范(事务管理器规范接口和事务增强等等)
- spring-jdbc: 包含DataSource方式事务管理器实现类DataSourceTransactionManager
- spring-orm: 包含其他持久层框架的事务管理器实现类例如:Hibernate/Jpa等
Spring声明式事务对应事务管理器接口:
使用案例
- 引入依赖
|
|
- 配置事务管理器
|
|
- 启用声明式注解@Transactional
|
|
- 测试事务效果
|
|
事务属性
- 只读
|
|
对一个方法来说,离它最近的 @Transactional 注解中的事务属性设置生效。因此方法上的注解可以覆盖类上的注解。对一个查询操作来说,如果我们把它设置成只读,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。
- 超时时间
|
|
超时回滚,释放资源。
- 事务异常
|
|
默认只针对运行时异常回滚。
- 事务隔离级别
|
|
-
读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。
-
读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。(Oracle默认隔离级别)。
-
可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。(MySQL默认隔离级别)
-
串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。
-
事务传播级别
|
|
名称 | 含义 |
---|---|
REQUIRED 默认值 | 如果父方法有事务,就加入,如果没有就新建自己独立事务。 |
REQUIRES_NEW | 不管父方法是否有事务,都新建事务。 |