Spring事务管理(二)Spring中的事务管控

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gloomy_114/article/details/62233564

上一节中,我们了解了事务的基本概念,和多个事务并发运行时可能导致的问题。下面讲一下Spring中的事务管控。

1. Spring事务核心接口

    Spring事务管理中,主要的核心实现为org.springframework.transaction.PlatformTransactionManager接口。具体实现如下图所示。

Spring事务管理核心接口

  • TransactionDefinition:规范事务的特定表现形式
  • TransactionStatus:事务运转的状态形式
  • PlatformTransactionManager:根据给定的规则获取事务现有状态的具体表现,进行具体操作。

2. 事务特性

由上图,我们可以看出TransactionDefinition就是用来指定事务特性的。包含了以下内容:

2.1 事务传播行为
    事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
  • PROPAGATION_REQUIRED:当前方法必须在事务中运行,如果当前有事务环境就加入当前正在执行的事务环境,如果没有,则新建一个事务。此选项为默认值。
  • PROPAGATION_SUPPORTS:如果当前存在事务环境,该方法就加入事务中执行。如果当前没有事务,就以非事务的方式执行。
  • PROPAGATION_MANDATORY:当前方法必须在事务中运行,如果当前没有事务,就抛出异常。
  • PROPAGATION_REQUIRES_NEW:当前方法总是会为自己发起一个新的事务,如果当前方法已经运行在一个事务中,则原有事务被挂起,创建一个属于自己的事务,直到自身的事务commit结束,原有的事务才会恢复执行。
  • PROPAGATION_NOT_SUPPORTED:当前方法总是以非事务方式进行操作。如果当前存在事务,就把当前事务挂起,等该方法以非事务的状态运行完成,再继续原来的事务。
  • PROPAGATION_NEVER:当前方法总是以非事务方式进行操作。如果方法在事务范围内执行,容器则抛出异常。
  • PROPAGATION_NESTED:当前方法执行时,如果已经有一个事务存在,则以嵌套事务的方式运行在当前事务中。子事务可以单独的进行回滚提交操作,不会对父事务造成影响。但是子事务要受父事务的影响。
2.2 事务隔离级别
事务隔离级别,是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:

- ISOLATION_DEFAULT:采用数据库默认隔离级别
- ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- ISOLATION_READ_COMMITTED:大多数主流数据库的默认事务等级。保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了脏读。该级别使用与大多数系统。
- ISOLATION_REPEATABLE_READ:保证一个事务不会修改已经由另一个事务读取但为提交(回滚)的数据,也就是对同一字段在同一事务中多次读取的结果都是一致的。避免了脏读和不可重复读的情况,但是带来了更多的性能损耗。
- ISOLATION_SERIALIZABLE:最严格的级别,事务串行执行,资源消耗最大。

2.3 事务超时
    事务超时,指的是设置事务执行的最长时间,如果超过时间事务还没有执行完成便立即回滚该事务。在 TransactionDefinition 中以 int 的值来表示超时时间,单位为是秒。
2.4 事务只读属性
    事务只读,指的是操作数据库时,只进行读取操作,而不会做相应的修改。只读属性并不是强制性的选项,而是一种优化配置。它将只读配置信息传递给数据库,以期待数据库会对其做一些特定化的优化。例如,不安排相应的数据库锁,以减轻事务对数据库的压力等。
2.5 事务回滚规则
     默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。可以明确的配置在抛出那些异常时回滚事务,包括checked异常。

PS.RuntimeException + Error 和其子类都是属于 uncheck exception
Exception类中除了 RuntimeException之外的类 都是属于 check exception

3. 事务管理器

    从上图可以看出,Spring本身并不管理事务,而是提供了许多的事务管理器,这些事务管理器都实现了org.springframework.transaction.PlatformTransactionManager接口,并且进行个性化的实现,达到事务管理的目的。
3.1 DataSourceTransactionManager
    DataSourceTransactionManager主要使用于由JDBC直接持久化数据的情况,例如Mybatis等。它通过调用java.sql.connection来管控事务,并且指定相应的DataSource。但是这并不意味着Connection具备事务功能,它仅仅是将commit,rollback等命令传递给数据库,由数据库本身的事务进行管理。并且像commit,rollback等事务功能和执行SQL的业务功能必须使用同一个Connection,才能真正实现事务管控的功能。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"/>
</bean>
3.2 HibernateTransactionManager
    HibernateTransactionManager主要使用于由Hibernate框架持久化数据的情况。它将事务功能和业务功能分隔开来,由Hibernate自身的Transaction来管理事务,使职责更为分明清晰。
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
</bean>
3.3 JpaTransactionManager
JpaTransactionManager主要使用于通过Java持久化API来持久化数据的情况。它需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现),并且JpaTransactionManager将与由工厂所产生的JPA EntityManager合作来构建事务。
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
</bean>
3.4 JtaTransactionManager
JtaTransactionManager主要使用于包含多个数据源的分布式事务管控。

4. @Transactional

@Transactional注解可以作用在接口,接口方法,类以及类方法上。当作用在类上时,该类所有的public方法都将具有该类型的事务属性。作用在方法上的标注将覆盖类级别的定义。

注意:在Spring中,建议不要在接口或者接口方法上使用该注解。因为Spring的代理方式分为基于接口的代理和基于类实现的代理,只有当Spring在使用基于类的代理时,注解才会生效。另外,@Transactional注解应该只被应用到public方法上,这是由Spring AOP本质决定的。应用在非public方法上,注解会被忽略,也不会抛出异常。

Spring AOP代理对象的生成有两种:JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。接口中不允许出现private、protected方法,同样子类实现中也不会出现private、protected等默认可见性方法。所以是无法被AOP所拦截,进而@Transactional注解不起效。

没有更多推荐了,返回首页