zoukankan      html  css  js  c++  java
  • 第5章 Spring的事务管理

    5.1 Spring事务管理概述

    5.11 事务管理的核心接口

    在Spring的所有jar包中,有一个名spring-tx-4.3.6RELEAS的jar包,是提供事务管理的依赖包。在该包的org.springframework.transaction包中,三个核心接口文件分别是PlatformTransactionManagerTransactionDefinitionTransactionStatus

    1.PlatfromTransactionManager

    PlatfromTransactionManager接口是Spring提供的平台事务管理器,主要用于管理事务。有3个事务操作的方法:

    TransactionStatus getTransaction( TransactionDefinition definition ):用于获取事务状态信息

    void commit( TransactionStatus status ):提交事务

    void rollback( Transaction status ):回滚事务

    PlatformTransactionManager接口只是代表事务管理的接口,并不知道底层是如何管理事务的,具体如何管理事务则由它的实现类来完成。该接口常见的几个实现类如下:

    (1)、用于配置JDBC数据源的事务管理器:
    org.springframework.jdbc.datasource.DataSourceTransactionManager
    (2)、用于配置Hibernate的事务管理器:
    org.springframework.orm.hibernate4.HibernateTransactionManager
    (3)、用于配置全局事务管理器:
    org.springframework.transaction.jta.JtaTransactionManager

    当底层采用不同的持久层技术时,系统只需使用不同的实现类。

    2.TransactionDefinition

    事务定义(描述)的对象,该对象中定义了事务规则,并提供获取事务相关信息的方法,具体如下:

    String getName():获取事务对象名称

    int getlsolationLevel:获取事务的隔离级别

    int getPropagationBehavior():获取事务的传播行为

    int getTimeout():获取事务的超时时间

    boolean isReadOnly():获取事务的是否只读

    传播行为:指在同一个方法中,不同操作前后所使用的事务。传播行为有很多种:

    传播行为可以控制是否需要创建事务以及如何创建事务,查询不影响数据的改变,不需要事务管理;插入、更新和删除需要事务管理。如果没有指定事务的传播行为,Spring默认传播行为是REQUIRED(required)

    3.TransactionStatus

    TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息,该接口有6个方法:

    void flush():刷新事务

    boolean hasSavepoint():获取是否存在保存点

    boolean isCompleted():获取事务是否完成

    boolean isNewTransaction():获取是否是新事物

    boolean isRollbackOnly():获取是否回滚

    void setRollbackOnly():设置事务回滚

    5.12 事务管理的方式:

    传统的编程式事务管理:通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚

    声明式事务管理:通过AOP技术实现的事务管理,主要思想是将事务管理作为一个“切面”代码单独编写,然后通过AOP技术将管理“切面”代码织入到业务目标类中。

    5.2 声明式事务管理

    5.21 基于XML方式的声明式事务

    tx命名空间下提供了<tx:advice>元素来配置事务的通知(增强处理)。当使用<tx:advice>元素配置了事务的增强处理后,就可以通过编写AOP配置,让Spring自动对目标生成代理。

    配置<tx:advice>元素时,通常需要指定id和transaction-manager属性。transaction-manager属性用于指定事务管理器。除此之外,还需要配置一个<tx:attributes>子元素,该子元素可以通过配置多个<tx:method>子元素来配置执行事务的细节。

     转账方法编写:

            /**
         *  转账
         *  inUser:收款人
         *  outUser:汇款人
         *  money:收款金额
        */
        public void transfer(String outUser, String inUser, Double money) {
            // 收款时,收款用户的余额=现有余额+所汇金额
            this.jdbcTemplate.update("update account set balance = balance +? "
                    + "where username = ?",money, inUser);
            // 模拟系统运行时的突发性问题
            int i = 1/0;
            // 汇款时,汇款用户的余额=现有余额-所汇金额
            this.jdbcTemplate.update("update account set balance = balance-? "
                    + "where username = ?",money, outUser);
        }                

    XML文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
        
        <!-- 1.配置数据源 -->
        <bean id="dataSource222" 
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        
            <!--数据库驱动 -->
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            
            <!--连接数据库的url -->
            <property name="url" value="jdbc:mysql://localhost/spring" />
            
            <!--连接数据库的用户名 -->
            <property name="username" value="root" />
            
            <!--连接数据库的密码 -->
            <property name="password" value="****" />
       </bean>
       
       <!-- 2.配置JDBC模板 -->
       <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              
             <!-- 默认必须使用数据源 -->
             <property name="dataSource" ref="dataSource222" />
             
       </bean>
       
       <!--3.定义id为accountDao的Bean -->
       <bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
       
             <!-- 将jdbcTemplate注入到AccountDao实例中 -->
             <property name="jdbcTemplate" ref="jdbcTemplate" />
       </bean>    
       
       <!-- 4.事务管理器,依赖于数据源 -->
       <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            
            <property name="dataSource" ref="dataSource222" />
       </bean>    
       
       <!-- 5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
       <tx:advice id="txAdvice123" transaction-manager="transactionManager">
            <tx:attributes>
                <!-- name:*表示任意方法名称,传播行为,隔离级别,是否只读-->
                <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false" />
            </tx:attributes>
        </tx:advice>
        
        <!-- 6.编写AOP,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
        <aop:config>
            <!-- 切入点 -->
            <aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))"
                id="txPointCut111" />
            <!-- 切面:将切入点与通知整合 -->
            <aop:advisor advice-ref="txAdvice123" pointcut-ref="txPointCut111" />
        </aop:config>
    </beans>

    测试类:获取实例,调用方法,常规操作

    @Test///基于XML方式的声明式事务
        public void xmlTest(){
            ApplicationContext applicationContext = 
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            
            // 获取AccountDao实例
            AccountDao accountDao = 
                    (AccountDao)applicationContext.getBean("accountDao");
            
            // 调用实例中的转账方法
            accountDao.transfer("Jack", "Rose", 100.0);
            
            // 输出提示信息
            System.out.println("转账成功!");
        }

    5.22 基于Annotation(注解)方式的声明式事务

    两个套路

    1.在Spring容器中注册事务注解驱动:

    <tx:annotation-driven transaction-manager="transactionManager"/>

    XML文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
        <!-- 1.配置数据源 -->
        <bean id="dataSource" 
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        
            <!--数据库驱动 -->
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            
            <!--连接数据库的url -->
            <property name="url" value="jdbc:mysql://localhost/spring" />
            
            <!--连接数据库的用户名 -->
            <property name="username" value="root" />
            
            <!--连接数据库的密码 -->
            <property name="password" value="17251104238" />
        </bean>
        
        <!-- 2.配置JDBC模板 -->
        <bean id="jdbcTemplate" 
                class="org.springframework.jdbc.core.JdbcTemplate">
            
            <!-- 默认必须使用数据源 -->
            <property name="dataSource" ref="dataSource" />
        
        </bean>
        
        <!--3.定义id为accountDao的Bean -->
        <bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
            <!-- 将jdbcTemplate注入到AccountDao实例中 -->
            <property name="jdbcTemplate" ref="jdbcTemplate" />
        </bean>
        
        <!-- 4.事务管理器,依赖于数据源 -->
        <bean id="transactionManager" class=
         "org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>    
        
        <!-- 5.注册事务管理器驱动 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
        
    </beans>

    2.在方法transfer()前加注解:

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)

    方法:

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
        public void transfer(String outUser, String inUser, Double money) 
        {
            // 收款时,收款用户的余额=现有余额+所汇金额
            this.jdbcTemplate.update("update account set balance = balance +? "
                    + "where username = ?",money, inUser);
            
            // 模拟系统运行时的突发性问题
            //int i = 1/0;
            // 汇款时,汇款用户的余额=现有余额-所汇金额
            this.jdbcTemplate.update("update account set balance = balance -? "
                    + "where username = ?",money, outUser);
        }
  • 相关阅读:
    地三鲜
    在linux下使用am335x的DMA
    通过tarball形式安装HBASE Cluster(CDH5.0.2)——集群安装总览
    通过tarball形式安装HBASE Cluster(CDH5.0.2)——如何配置分布式集群中的zookeeper
    如何通过SSH及其Client 批量分发文件和执行管理命令
    解决ESXi有虚拟机模版部署的CentOS虚拟机,网卡eth0找不到问题
    CentOS 65 安装vmware tools 杂记
    安装vmware vCenter Appliance
    使用FileZilla解决从Windows上传文件到Linux vsftpd的乱码问题!
    不关闭seLinux解决vsftpd服务本地用户不能登录问题(500 OOPS: cannot change directory:/home/***)
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/10917424.html
Copyright © 2011-2022 走看看