• Spring---事务管理


    一.数据库事务基础知识

    1.何为数据库事务

    事务必须同时满足四个特性(ACID):原子性、一致性、隔离性和持久性。

    原子性:表示组成一个事务的所有数据操作是一个不可分割的原子单元,只有所有操作都执行成功,整个事务才会提交。

    一致性:事务操作成功后,数据库所处的状态和它的业务规则是一致的,即数据不会被破坏。

    隔离性:在并发数据操作时,不同的事务拥有各自的数据空间,他们的操作不会对对方产生干扰。

    持久性:一旦事务提交成功后,事务中所有的数据操作都必须持久化到数据库中。

    2.数据并发的问题

    数据并发导致的问题有:脏读、不可重复读、幻象读、第一类丢失更新、第二类丢失更新。

    脏读、不可重复读、幻读三个问题都是由于事务A对数据进行修改、增加,事务B总是在做读操作。而丢失更新问题则是由于两事务都在对数据进行修改。

    3.数据库锁机制

    数据库通过锁的机制解决并发访问问题。按锁定的对象的不同,可分为表锁定和行锁定;从并发事务锁定的关系上看,可以分为共享锁定和独占锁定。

    1)表共享锁定:通过 lock table in share mode 语句显示获得

    2)行共享锁定:通过 lock table in row share mode 语句显示获得,或者通过 select for update 

    3)表独占锁定:通过 lock table in exclusive  mode 语句显示获得 

    4)行独占锁定:通过 lock table in row exclusive mode 语句显示获得,或者通过 insert、update、delete

    5)表共享行独占锁定:通过 lock table in share row exclusive  mode 语句显示获得  

    4.事务隔离级别

    虽然数据库为用户提供了锁的DML操作方式,但直接使用锁管理师非常麻烦的,因此数据库为用户提供了自动锁机制,只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据资源添加合适的锁。

     ANNSI/ISO SQL 92标准定义了4个等级的事务隔离级别。read uncommitted  <  read committed<   repeatable read <   serializale

    注意:并不是所有的数据库都支持事务,即使数据库支持事务,也并非支持所有的事务隔离级别。

    二.Spring为不同的持久化框架提供了不同的事务管理器实现类。

    持久层技术                                                            事务管理器类实现类

    Spring JDBC 和 iBatis                                           DataSourceTransactionManager

    JPA                                                                       JpaTransactionManager

    Hibernate                                                              HibernateTransactionManager

    JTA                                                                       JtaTransactionManager---------具有多个数据源的全局事务使用该事务管理器

    JDO                                                                      org.springframework.orm.jdo.IdoTransactionManager   不常用

    三.事务管理方式--Spring既支持编程式事务管理,也支持声明式的事务管理

    编程式事务管理:通过代码控制事务的提交和回滚。

    声明式事务管理:将事务管理代码从业务方法中分离出来,通过配置来实现事务管理。核心基于AOP实现。

    1.编程式的事务管理

    jdbc代码:conn.setAutoCommite(false);

    Hibernate代码:session.beginTransaction();//开启事务

    2.使用xml配置声明式事务

    实现步骤:
    1.引入spring-sop相关的4个jar文件
    2.引入aop名称空间(xml配置方式需要引入)
    3.引入tx名称空间(事务方式必须引入)

    例如,我们想通过spring的声明事务来让以下接口的delete()和update()方法拥有写事务的能力,而其他方法只拥有读事务的能力。

    package com.testMyBatis.service;
    public class BookService { private BookDao bookdao; public List<Book> getAllBooks() { return bookdao.getAllBooks(); } public Book getBookById(int id) { return bookdao.getBookById(id); }

    public int delete(int id) { return bookdao.delete(id); }

    public int update(Book entity) { return bookdao.update(entity); } }

     Spring基本配置

        <!--配置事务管理器(不同的持久类对应不同的事物管理器实现类) -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"></property>
        </bean>   

    1)使用原始的TransactionProxyFactoryBean

        <!--1.需要实现事务增强的目标业务Bean-->
        <bean id="BookServiceTarget"  class="com.testMyBatis.service.BookService">
            <property name="bookdao" ref="bookdao"></property>
        </bean>
        <!--2.使用事务代理工厂类为目标业务Bean提供事务增强-->
        <bean id="BookService"  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager" ref="transactionManager"></property>
            <property name="target" ref="BookServiceTarget"></property>
            <property name="transactionAttribubutes" >
                 <props>
                      <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop><!--以get为前缀的方法拥有只读事务属性-->
                      <prop key="*">PROPAGATION_REQUIRED</prop><!--目标bean中所有方法拥有可写事务属性-->
                 </props>
            </property>
        </bean>

    2)基于tx/aop命名空间的配置

       <!--配置事务增强(如何管理事务?)-->    
    <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="delete" rollback-for="Exception"/> <tx:method name="update" /> </tx:attributes> </tx:advice>

    <!--AOP配置,拦截那些方法(切入点表示式)+应用上面的事务增强配置-->
    <aop:config> <aop:pointcut id="serviceMethod" expression="execution("com.testMyBatis.service.BookService.*(..)")"/> <aop:advisor advice-ref="serviceMethod" advice-ref="txAdvice"/> </aop:config>

     注意:<tx:method>元素属性有:

                 name:必须属性,与事务属性关联的方法,可使用通配符*

                 propagation:非必需元素,事务传播行为,默认值是REQUIRED

                 isolation:非必需元素,事务隔离级别,默认值是DEFAULT

                 timeout:非必需元素,超时,默认值是-1

                 read-only:非必需元素,读写事务,默认值是false

                 rollback-for:非必需元素,回滚,默认值是所有运行期异常都回滚

                 no-rollback-for:非必需元素,默认值是所有检查型异常不回滚

    3.使用注解配置声明式事务

    1.在需要添加事务控制的地方,即业务类使用@Transactional注解

    注意:@Transactional的8个属性:

                 propagation:非必需元素,事务传播行为,默认值是Propagation_REQUIRED

                 isolation:非必需元素,事务隔离级别,默认值是Isolation_DEFAULT

                 timeout:非必需元素,超时,int型,以秒为单位

                 readOnly:非必需元素,读写事务,默认值是false

                 rollbackFor:非必需元素,回滚,默认为{},类型为Class[],例如{SQLException.calss},多个异常之间用逗号分隔

                 noRollbackFor:非必需元素,默认为{}         

                 rollbackForClassName:非必需元素,回滚,默认为{},类型为String[]

                 noRollbackForClassName:非必需元素,默认为{}

    2.基于aop/tx命名空间的配置

        <!--支持注解驱动的事务管理,指定事务管理器(@Transactional使事务注解生效) -->
        <tx:annotation-driven transaction-manager="transactionManager" />

    注意:<tx:annotation-driven >具有三个属性

               1)transaction-manager:如果用户事务管理器id为transactionManager,可简化为<tx:annotation-driven />

               2)proxy-target-class:如果为true,Spring将通过创建子类来代理业务类,如果为false,则使用基于接口的代理

               3)order:如果业务类除事务切面外,还需要织入其他的切面,通过该属性可以控制织入顺序

    注意事项:1.Spring建议在具体业务上使用@Transactional注解,这样,不管<tx:annotation-driven >的proxy-target-class的属性配置是哪个,业务类都会启用事务机制。

                     2.方法上的注解会覆盖类定义处的注解

                     3.如果一个应用具有多个事务管理器,如果我们希望不同的地方使用不同的事务管理器,只需像下面配置,为事务管理器标志一个名字

        <bean id="transactionManager1"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"></property>
    <qualifier value="tm1"/> </bean>

    然后,用上注解@Transactional(tm1)

    Spring的事务管理

  • 相关阅读:
    JS练习
    推断一组数的规律,并填充缺失的数
    IP地址的正则表达式写法
    相比于HTML4,HTML5废弃的元素有哪些?
    关于HTML5和CSS3的几个“新增”
    hdu 3092 简单数论+分组背包dp
    避障
    人工势场法
    A*
    pop 2049-简单bfs
  • 原文地址:https://www.cnblogs.com/mcahkf/p/8098292.html
Copyright © 2020-2023  润新知