1. 引言  事务特性

事务是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性。事务通常是以begin transaction开始,以commit或rollback结束。Commint表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据的更新写回到磁盘上的物理数据库中去,事务正常结束。Rollback表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态。

  原子性(Atomic) 对数据的修改要么全部执行,要么全部不执行。

  一致性(Consistent) 在事务执行前后,数据状态保持一致性。

  隔离性(Isolated) 一个事务的处理不能影响另一个事务的处理。

  持续性(Durable) 事务处理结束,其效果在数据库中持久化。

 2. Java事务的类型

Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。

1、JDBC事务

JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法:

  public void setAutoCommit(boolean)
  public boolean getAutoCommit()
  public void commit()
  public void rollback()

使用 JDBC 事务界定时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。

2、JTA(Java Transaction API)事务

JTA是一种高层的,与实现无关的,与协议无关的API,应用程序和应用服务器可以使用JTA来访问事务。

JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据,这些数据可以分布在多个数据库上。JDBC驱动程序的JTA支持极大地增强了数据访问能力。

如果计划用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。

您将需要用应用服务器的管理工具设置 XADataSource .从应用服务器和 JDBC 驱动程序的文档中可以了解到相关的指导。

J2EE应用程序用 JNDI 查询数据源。一旦应用程序找到了数据源对象,它就调用 javax.sql.DataSource.getConnection() 以获得到数据库的连接。

XA 连接与非 XA 连接不同。一定要记住 XA 连接参与了 JTA 事务。这意味着 XA 连接不支持 JDBC 的自动提交功能。同时,应用程序一定不要对 XA 连接调用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() .

相反,应用程序应该使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() .

3、容器事务

容器事务主要是J2EE应用服务器提供的,容器事务大多是基于JTA完成,这是一个基于JNDI的,相当复杂的API实现。相对编码实现JTA事务管理, 我们可以通过EJB容器提供的容器事务管理机制(CMT)完成同一个功能,这项功能由J2EE应用服务器提供。这使得我们可以简单的指定将哪个方法加入事 务,一旦指定,容器将负责事务管理任务。这是我们土建的解决方式,因为通过这种方式我们可以将事务代码排除在逻辑编码之外,同时将所有困难交给J2EE容 器去解决。使用EJB CMT的另外一个好处就是程序员无需关心JTA API的编码,不过,理论上我们必须使用EJB.

4、三种Java事务差异

  JDBC事务控制的局限性在一个数据库连接内,但是其使用简单。

   JTA事务的功能强大,事务可以跨越多个数据库或多个DAO,使用也比较复杂。

  容器事务,主要指的是J2EE应用服务器提供的事务管理,局限于EJB应用使用。

5、应用场景

Java事务控制是构建J2EE应用不可缺少的一部分,合理选择应用何种事务对整个应用系统来说至关重要。一般说来,在单个JDBC 连接连接的情况下可以选择JDBC事务,在跨多个连接或者数据库情况下,需要选择使用JTA事务,如果用到了EJB,则可以考虑使用EJB容器事务

3. spring事务实现源码分析

 3.1 dao模块    dao模块定义了数据库层的各种异常,其中异常的结构已经在spring-jdbc模块中介绍过了,在这里主要是dao的支持和异常的转译,其数据库支持和转译结构如下所示:

dao 支持提供了对hibernate、jdbc,cci的支持。我们都想到熟悉,对cci可能有些陌生,下面的章节会讲到。
dao异常转译  PersistenceExceptionTranslationPostProcessor:自动将标示为@repository的bean的持久化异常进行转译。它增加一个PersistenceExceptionTranslationAdvisor来代理相应的已经存在的aop代理或者实现了目标接口的新产生的代理。它将本地资源异常转换为spring的DataAccessException及其子类上。

  PersistenceExceptionTranslationAdvisor是一个spring aop的异常转译类,它应用到respository层或者dao层。它基于给定的PersistenceExceptionTranslator来将本地持久化异常转换为spring的DataAccessException族。

 PersistenceExceptionTranslationInterceptor:一个aop 方法拦截器(MethodInterceptor).提供基于PersistenceExceptionTranslator的异常转换,它是PersistenceExceptionTranslator的代理,将运行时抛出的异常转换为spring 的DataAccessException族。

  PersistenceExceptionTranslator spring集成其它数据获取技术(如jpa、toplink、jdo、hibernate等)抛出运行时异常的接口。

3.2 jca模块
   1. cci模块

J2EE提供JCA(Java Connector Architecture)规范来标准化对EIS(Enterprise Information System)的访问。这个规范被分为几个不同的部分: 

  SPI(Service provider interfaces)是连接器提供者(connector provider)必须实现的接口。 这些接口组成了一个能被部署在J2EE应用服务器上的资源适配器(resource adapter)。 在这种情况下,由服务器来管理连接池(connection pooling)、事务和安全(托管模式(managed mode))。 应用服务器还负责管理客户端应用程序之外所拥有的配置。连接器(connector)同样能在脱离应用服务器的情况下使用;在这种情况下,应用程序必须直接对它进行配置(非托管模式(non-managed mode))。 

  CCI (Common Client Interface)是应用程序用来与连接器交互并与EIS通信的接口。同样还为本地事务划界提供了API。 

  Spring对CCI的支持,目的是为了提供以典型的Spring方式来访问CCI连接器的类,并有效地使用Spring的通用资源和事务管理工具。 

注意: 连接器的客户端不必总是使用CCI。 某些连接器暴露它们自己的API,只提供JCA资源适配器(resource adapter) 以使用J2EE容器的某些系统契约(system contracts)(连接池(connection pooling),全局事务(global transactions),安全(security))。 Spring并没有为这类连接器特有(connector-specific)的API提供特殊的支持。
 2. context模块    ResourceAdapterApplicationContext:一个jca ResourceAdapter的applicationContext实现,需要于jca的bootstrapContext一同初始化,最后传递到实现了BootstrapContextAware的spring 受管理bean。
    @Overrideprotected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {beanFactory.addBeanPostProcessor(new BootstrapContextAwareProcessor(this.bootstrapContext));beanFactory.ignoreDependencyInterface(BootstrapContextAware.class);beanFactory.registerResolvableDependency(BootstrapContext.class, this.bootstrapContext);// JCA WorkManager resolved lazily - may not be available.beanFactory.registerResolvableDependency(WorkManager.class, new ObjectFactory<WorkManager>() {@Overridepublic WorkManager getObject() {return bootstrapContext.getWorkManager();}});}

BootstrapContextAwareProcessor:传递BootstrapContext到实现了BootStrapContextAware接口的spring bean。它在内部bean factory中自动注册。
BootstrapContextAware:需要通知BootStrapContext的实现类。
BootstrapContext:提供一种机制,这种机制将一个Bootstrap的上下文传递到一个资源适配器实例。
3.endpoint模块  AbstractMessageEndpointFactory:实现了jca 1.5、1.6、1.7版本的javax.resource.spi.endpoint.MessageEndpointFactory接口,它提供了事务管理能力。  GenericMessageEndpointFactory实现了抽象方法,对任意类型的消息监听对象(javax.jms.MessageListener)或者javax.resource.cci.MessageListener对象提供了事务管理的能力。  GenericMessageEndpointManager管理类,对上述方法进行管理。 4.support模块   LocalConnectionFactoryBean:创建一个本地JCA连接工厂。   ResourceAdapterFactoryBean :使用BootStrapContext启动一个jca 1.5指定的ResouceAdapter。 5. work模块   结构如下:

WorkManager提供了提交Work(Work继承了Runnable)可执行实例的便利类。
3.3 transaction模块

spring事务架构

3.3.1 事务管理PlatformTransactionManager的架构

如下图所示:

PlatformTransactionManager:spring事务的核心接口。

3.3.2 事务定义TransactionDefinition的架构

如下图所示:

TransactionDefinition:定义spring容器事务属性的接口。

包括事务传播行为类型和事务隔离级别:

事务传播行为类型

事务传播行为类型

说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

当使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC 3.0,并且实现者需要支持保存点事务机制。

隔离级别:

为了避免上面出现几种情况在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同

  1. 未授权读取(Read Uncommitted):也称未提交读。防止更新丢失(这不对应一级锁吗),如果一个事务已经开始写数据则另外一个数据则不允许同时进行写操作但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。事务隔离的最低级别,仅可保证不读取物理损坏的数据。与READ COMMITTED 隔离级相反,它允许读取已经被其它用户修改但尚未提交确定的数据。

  2. 授权读取(Read Committed):也称提交读。1之上防止脏读取(这不对应二级锁吗)。这可以通过“瞬间共享读锁”和“排他写锁”实现,读取数据的事务允许其他事务继续访问该行数据,但是未提交写事务将会禁止其他事务访问该行。SQL Server 默认的级别。在此隔离级下,SELECT 命令不会返回尚未提交(Committed) 的数据,也不能返回脏数据。

  3. 可重复读取(Repeatable Read):2之上防止不可重复读取(这不对应三级锁吗)。但是有时可能出现幻影数据,这可以通过“共享读锁”和“排他写锁”实现,读取数据事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。在此隔离级下,用SELECT 命令读取的数据在整个命令执行过程中不会被更改。此选项会影响系统的效能,非必要情况最好不用此隔离级。

  三级封锁协议并不能阻止幻读,修改的不能再被读取,但是新增(删除)的记录数可以统计。

  4. 串行(Serializable):也称可串行读(这不对应两段锁吗)。提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过 “行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作事务访问到。事务隔离的最高级别,事务之间完全隔离。如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠事务均是串行的。

  LU丢失更新 DR脏读 NRR非重复读SLU二类丢失更新 PR幻像读

为了解决与“多个线程请求相同数据”相关的问题,事务之间用锁相互隔开。多数主流的数据库支持不同类型的锁;因此,JDBC API 支持不同类型的事务,它们由 Connection 对象指派或确定。 
为了在性能与一致性之间寻求平衡才出现了上面的几种级别。事务保护的级别越高,性能损失就越大。
假定您的数据库和 JDBC 驱动程序支持这个特性,则给定一个 Connection 对象,您可以明确地设置想要的事务级别:
conn.setTransactionLevel(TRANSACTION_SERIALIZABLE) ;
可以通过下面的方法确定当前事务的级别:
            int level = conn.getTransactionIsolation();

SavepointManager:管理事务savepoint的编程式API接口。

JDBC定义了SavePoint接口,提供在一个更细粒度的事务控制机制。当设置了一个保存点后,可以rollback到该保存点处的状态,而不是rollback整个事务。Connection接口的setSavepoint和releaseSavepoint方法可以设置和释放保存点。

TransactionStatus:事务状态表现形式。

 3.3.3 spring事务实现机制

1 高层

比较好的方式有:1.基于持久层api的模板方法;2.使用具有事务工厂bean的本地ORM api;3使用代理管理本地资源工厂。

2 底层

      DataSourceUtils (用作JDBC事务), EntityManagerFactoryUtils (用作JPA事务), SessionFactoryUtils (用作Hibernate事务),PersistenceManagerFactoryUtils (用作JDO事务)等等,

例如:在使用jdbc时,你可以不通过DataSource的getConnection()方法获取connection,而是使用以下方法获取:

  Connection conn = DataSourceUtils.getConnection(dataSource);
3 最低层TransactionAwareDataSourceProxy是事务的最底层,它代理了DataSource,并增加了spring管理事务功能。
参考资料:1.http://www.educity.cn/rk/457230.html2. http://uule.iteye.com/blog/14456783. http://zhxing.iteye.com/blog/368110

转载于:https://www.cnblogs.com/davidwang456/p/4309038.html

spring transaction源码分析--事务架构相关推荐

  1. 事务回滚什么意思 try_分布式事务 TCC-Transaction 源码分析——事务恢复

    1. 概述 本文分享 TCC 恢复.主要涉及如下二个 package 路径下的类: org.mengyun.tcctransaction.recover RecoverConfig,事务恢复配置接口 ...

  2. 一步一步手绘Spring AOP运行时序图(Spring AOP 源码分析)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  3. 视频教程-Spring底层源码分析-Java

    Spring底层源码分析 鲁班学院-子路老师曾就职于谷歌.天猫电商等多家互联网公司,历任java架构师.研发经理等职位,参与并主导千万级并发电商网站与后端供应链研发体系搭建,多次参与电商大促活动技术保 ...

  4. Spring Cloud源码分析(二)Ribbon(续)

    因文章长度限制,故分为两篇.上一篇:<Spring Cloud源码分析(二)Ribbon> 负载均衡策略 通过上一篇对Ribbon的源码解读,我们已经对Ribbon实现的负载均衡器以及其中 ...

  5. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  6. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  7. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  8. spring AOP源码分析(一)

    spring AOP源码分析(一) 对于springAOP的源码分析,我打算分三部分来讲解:1.配置文件的解析,解析为BeanDefination和其他信息然后注册到BeanFactory中:2.为目 ...

  9. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    概述 我们知道 Spring Boot 能够创建独立的 Spring 应用,内部嵌入 Tomcat 容器(Jetty.Undertow),让我们的 jar 无需放入 Servlet 容器就能直接运行. ...

最新文章

  1. 专访 | 融资4.1亿美元,估值15亿美元,这家AI初创公司凭什么“这么贵”?
  2. 5G与AI深度融合,人类世界即将产生巨变
  3. sql中union 和 union all的区别
  4. 多线程编程之线程同步主要函数一览
  5. encipher.min.php,陌屿授权系统(5.7)最新版 网站授权 - 下载 - 搜珍网
  6. oracle 微信公众号,关于微信公众号贴代码的方法
  7. (转)使用Spring配置文件实现AOP
  8. 2018-2019-2 20175215 实验五《网络编程与安全》实验报告
  9. 《软件需求最佳实践》——阅读笔记一
  10. 在VC中使用Windows管道技术编程
  11. Android 学习笔记之Volley(七)实现Json数据加载和解析...
  12. Go runtime发展历程图片
  13. [零基础学Python]字典,你还记得吗?
  14. Linux cat命令使用
  15. 89c51单片机汇编语言,AT89C2051时钟程序——MCS51单片机汇编程序
  16. 支付宝手机网站支付、支付查询、退款、退款查询、转账接口整合
  17. 微信公众号网页授权,获取用户信息以及openid -- PHP后台
  18. nRF24L01--2.4G无线通信模块(1)(51单片机和51单片机通信)
  19. 通关Bandit(0-32)命令大全
  20. C++信号量实现线程间同步,windows使用SetEvent,linux使用sem_t,QT测试

热门文章

  1. python3.6小程序_python3.6 tkinter实现屏保小程序
  2. python迷宫问题的所有路径_python——迷宫问题总结
  3. java8函数式编程 视频_快速掌握Java8 Stream函数式编程技巧
  4. dva的用法_dva.js 用法详解:列表展示
  5. druid mysql配置详解_druid配置详解
  6. linux 系统时间是在哪里记录的,Linux系统如何记录时间
  7. mysql缓存hibernate_关于Hibernate缓存机制
  8. python 修改文件名_Python 批量修改文件名
  9. 函数指针,以及用函数指针的好用之处(回调函数)
  10. android 树形目录结构的实现(包含源码)