我们知道,在JavaEE的开发过程中,service方法用于处理主要的业务逻辑,而业务逻辑的处理往往伴随着对数据库的多个操作。以我们生活中常见的转账为例,service方法要实现将A账户转账到B账户的功能,则该方法内必定要有两个操作:先将A账户的金额减去要转账的数目,然后将B账户加上相应的金额数目。这两个操作必定要全部成功,方才表示本次转账成功;若有任何一方失败,则另一方必须回滚(即全部失败)。事务指的就是这样一组操作:这组操作是不可分割的,要么全部成功,要么全部失败
事务的特性事务具有ACID四个特性:
原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
一致性(Consistency):事务在完成后数据的完整性必须保持一致
隔离性(Isolation):多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间的数据要相互隔离
持久性(Durability):一个事务一旦被提交,它对数据库中数据的改变应该是永久性的,即使数据库发生故障也不应该对其有任何影响
Spring 事务管理为我们提供了三个高层抽象的接口,分别是TransactionProxyFactoryBean,TransactionDefinition,TransactionStatus
1.PlatformTransactionManager事务管理器Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,Spring框架并不直接管理事务,而是通过这个接口为不同的持久层框架提供了不同的PlatformTransactionManager接口实现类,也就是将事务管理的职责委托给Hibernate或者iBatis等持久化框架的事务来实现
org.springframework.jdbc.datasource.DataSourceTransactionManager:使用JDBC或者iBatis进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager:使用hibernate5版本进行持久化数据时使用
org.springframework.orm.jpa.JpaTransactionManager:使用JPA进行持久化数据时使用
org.springframework.jdo.JdoTransactionManager:当持久化机制是jdo时使用
org.springframework.transaction.jta.JtaTransactionManager:使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用
PlatformTransactionManager接口源码:
public interface PlatformTransactionManager { //事务管理器通过TransactionDefinition,获得“事务状态”,从而管理事务 TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; //根据状态提交 void commit(TransactionStatus var1) throws TransactionException; //根据状态回滚 void rollback(TransactionStatus var1) throws TransactionException; } 2.TransactionDefinition定义事务基本属性org.springframework.transaction.TransactionDefinition接口用于定义一个事务,它定义了Spring事务管理的五大属性:隔离级别、传播行为、是否只读、事务超时、回滚规则
2.1隔离级别什么是事务的隔离级别?我们知道,隔离性是事务的四大特性之一,表示多个并发事务之间的数据要相互隔离,隔离级别就是用来描述并发事务之间隔离程度的大小
在并发事务之间如果不考虑隔离性,会引发如下安全性问题:
脏读 :一个事务读到了另一个事务的未提交的数据
不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致
幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致
在 Spring 事务管理中,为我们定义了如下的隔离级别:
ISOLATION_DEFAULT:使用数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取已改变而没有提交的数据,可能会导致脏读、幻读或不可重复读
ISOLATION_READ_COMMITTED:允许读取事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据事务本身改变,可以阻止脏读和不可重复读,但幻读仍有可能发生
ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别,确保不发生脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的
Spring事务传播机制规定了事务方法和事务方法发生嵌套调用时事务如何进行传播,即协调已经有事务标识的方法之间的发生调用时的事务上下文的规则
Spring定义了七种传播行为,这里以方法A和方法B发生嵌套调用时如何传播事务为例说明:
PROPAGATION_REQUIRED:A如果有事务,B将使用该事务;如果A没有事务,B将创建一个新的事务
PROPAGATION_SUPPORTS:A如果有事务,B将使用该事务;如果A没有事务,B将以非事务执行
PROPAGATION_MANDATORY:A如果有事务,B将使用该事务;如果A没有事务,B将抛异常
PROPAGATION_REQUIRES_NEW:A如果有事务,将A的事务挂起,B创建一个新的事务;如果A没有事务,B创建一个新的事务
PROPAGATION_NOT_SUPPORTED:A如果有事务,将A的事务挂起,B将以非事务执行;如果A没有事务,B将以非事务执行
PROPAGATION_NEVER:A如果有事务,B将抛异常;A如果没有事务,B将以非事务执行
PROPAGATION_NESTED:A和B底层采用保存点机制,形成嵌套事务
如果将事务设置为只读,表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务
2.4事务超时