• Spring中的事务管理


    一、事务简介

            事务管理是企业级应用程序开发中必不可少的技术,  用来确保数据的完整性和一致性. 
            事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
            事务的四个关键属性(ACID)
                   原子性(atomicity): 事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成要么完全不起作用.
                    一致性(consistency): 一旦所有事务动作完成, 事务就被提交. 数据和资源就处于一种满足业务规则的一致性状态中.
                    隔离性(isolation): 可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏.
                    持久性(durability): 一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中
     

    Spring 中的事务管理

            作为企业级应用程序框架,Spring 在不同的事务管理 API 之上定义了一个抽象层. 而应用程序开发人员不必了解底层的事务管理 API, 就可以使用 Spring 的事务管理机制.
            Spring 既支持编程式事务管理, 也支持声明式的事务管理. 
                    编程式事务管理: 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚. 在编程式管理事务时, 必须在每个事务操作中包含额外的事务管理代码. 
                    声明式事务管理: 大多数情况下比编程式事务管理更好用. 它将事务管理代码从业务方法中分离出来, 以声明的方式来实现事务管理.事务管理作为一种横切关注点, 可以通过 AOP 方法模块化. Spring 通过 Spring AOP 框架支持声明式事务管理.
     

    Spring 中的事务管理器

            Spring 从不同的事务管理 API 中抽象了一整套的事务机制.开发人员不必了解底层的事务 API, 就可以利用这些事务机制. 有了这些事务机制, 事务管理代码就能独立于特定的事务技术了.
            Spring 的核心事务管理抽象是platform TransactionManage它为事务管理封装了一组独立于技术的方法. 无论使用 Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的.
     

    Spring 中的事务管理器的不同实现

            DataSoureTransactionManage :在应用程序中只需要处理一个数据源, 而且通过 JDBC 存取
            Jta TransactionManage : 在 JavaEE 应用服务器上用 JTA(Java Transaction API) 进行事务管理
            HibernateTransactionManage :用 Hibernate 框架存取数据库
    ……
    事务管理器以普通的 Bean 形式声明在 Spring IOC 容器中
     

    用 @Transactional 注解声明式地管理事务

            除了在带有切入点, 通知和增强器的 Bean 配置文件中声明事务外, Spring 还允许简单地用@Transactional 注解来标注事务方法. 
            为了将方法定义为支持事务处理的, 可以为方法添加 @Transactional 注解. 根据 Spring AOP 基于代理机制,只能标注公有方法.
            可以在方法或者类级别上添加 @Transactional 注解. 当把这个注解应用到类上时, 这个类中的所有公共方法都会被定义成支持事务处理的. 
            在 Bean 配置文件中只需要启用<tx:annotation-driven> 元素, 并为之指定事务管理器就可以了. 
    如果事务处理器的名称是 transactionManager, 就可以在<tx:annotation-driven> 元素中省略 transaction-manager 属性. 这个元素会自动检测该名称的事务处理器.
     
                    @Transactional
                    @Override
                    public void purchase(String username, String isbn) {
                            
                            bookShopDao.updateBookStock(isbn);
                            bookShopDao.updateUserAccount(username, price);
    }
     
                    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
                    <property name="dataSource" ref="dataSource"></property>  
                    </bean>  
          
                    <!-- 2. 配置事务属性 -->  
                    <tx:annotation-driven  transaction-manager="transactionManager"/> 
     

    二、事务属性

    事务传播属性

            当事务方法被另一个事务方法调用时, 必须指定事务应该如何传播. 例如: 方法可能继续在现有事务中运行, 也可能开启一个新事务, 并在自己的事务中运行.
            事务的传播行为可以由传播属性指定. Spring 定义了7  种类传播行为.(一二两种最常用)
                    (1)PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
                    (2)PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
                    (3)PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
                    (4)PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
                    (5)PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
                    (6)PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
                    (7)PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
     

    事务的隔离级别

            从理论上来说, 事务应该彼此完全隔离, 以避免并发事务所导致的问题. 然而, 那样会对性能产生极大的影响, 因为事务必须按顺序运行. 
            在实际开发中, 为了提升性能, 事务会以较低的隔离级别运行.
            事务的隔离级别可以通过隔离事务属性指定
                    1.ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
                    2.ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
                    3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
                    4.ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
                    5.ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。 
            事务的隔离级别要得到底层数据库引擎的支持, 而不是应用程序或者框架的支持.
            Oracle 支持的 2 种事务隔离级别:READ_COMMITED , SERIALIZABLE
            Mysql 支持 4 中事务隔离级别.
     

    事务回滚属性

            默认情况下只有未检查异常(RuntimeException和Error类型的异常)会导致事务回滚. 而受检查异常不会.
            事务的回滚规则可以通过@Transactional 注解的 rollbackFor 和 noRollbackFor 属性来定义. 这两个属性被声明为 Class[] 类型的, 因此可以为这两个属性指定多个异常类.
                    rollbackFor:  遇到时必须进行回滚
                    noRollbackFor: 一组异常类,遇到时必须不回滚
            
     

    超时和只读属性

            由于事务可以在行和表上获得锁,  因此长事务会占用资源, 并对整体性能产生影响. 
            如果一个事物只读取数据但不做修改, 数据库引擎可以对这个事务进行优化.
                    超时事务属性: 事务在强制回滚之前可以保持多久. 这样可以防止长期运行的事务占用资源.
                    只读事务属性: 表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务.
            超时和只读属性可以在 @Transactional 注解中定义.超时属性以秒为单位来计算.
            在 Spring 2.x 事务通知中, 超时和只读属性可以在<tx:method> 元素中进行指定.
     
            <!-- 2. 配置事务属性 -->
            <tx:advice id="txAdvice" transaction-manager="transactionManager">
                    <tx:attributes>
                            <!-- 根据方法名指定事务的属性 -->
                            <tx:method name="purchase" propagation="REQUIRES_NEW"
    isolation =“PROPAGATION_REQUIRES_NEW”rollback-for="java.io.Exception"timeout="30"read-only="true"/>
                    </tx:attributes>
            </tx:advice>
  • 相关阅读:
    Spring Security教程(一)
    java报错:The reference to entity "characterEncoding" must end with the ';' delimiter.
    SpringBoot定时任务升级篇(动态添加修改删除定时任务)
    SpringBoot几种定时任务的实现方式
    JDK中的Timer和TimerTask详解
    SpringMVC拦截器与SpringBoot自定义拦截器
    Java注解入门
    Servlet 4.0 入门
    spring邮件发送
    class path resource [spring/ApplicationContext-springmvc.xml] cannot be opened because it does not exist
  • 原文地址:https://www.cnblogs.com/hanxue112253/p/8514102.html
Copyright © 2020-2023  润新知