zoukankan      html  css  js  c++  java
  • spring 事务

    一:事务的配置

    spring 事务管理有两种方式

    1.声明式事务管理,在要管理的方法上添加@Transactional  写在service 的实现类或者dao层都可以

    2.配置式事务管理,在要管理的方法前后织入事务通知

    spring 配置文件 spring_coer.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:p="http://www.springframework.org/schema/p"
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
                            http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
                            http://www.springframework.org/schema/mvc  
                            http://www.springframework.org/schema/mvc/spring-mvc.xsd  
                            http://www.springframework.org/schema/context  
                            http://www.springframework.org/schema/context/spring-context.xsd
                                http://www.springframework.org/schema/aop   
                             http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
                             http://www.springframework.org/schema/tx 
                             http://www.springframework.org/schema/tx/spring-tx.xsd">
                             <!--Spring 整合mybaits-->
    <!-- 加载配置文件 -->
            <bean id="loadProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                    <property name="locations">
                        <list>
                            <value>classpath:db.properties</value>
                        </list>
                    </property>
            </bean>
    
        <!--配置注解扫描 use-default-filters 是扫描包括component 下的子注解 @service 等 -->
        <context:component-scan base-package="com.ssh"></context:component-scan>
        <!--sping 整合hibernate -->
    
      
        <!--定义basicDataSource数据源 -->
        <!-- org.apache.commons.dbcp2.datasources -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <!-- 指定连接数据库的驱动 -->
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <!-- 指定数据库所用的url -->
            <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/ssm"></property>
            <!--指定连接的用户名 -->
            <property name="user" value="root"></property>
            <!-- 指定连接的密码 -->
            <property name="password" value="123456"></property>
            <!-- 定义hibernate 的sessionFactory -->
        </bean>
     <!--                              方式一   声明式事务管理                                                    -->
        <tx:annotation-driven transaction-manager="transactionManager"/>



    <!-- spring 整合mybaits --> <!-- sprig 托管sqlSessionFactoryBean 作用:创建会话连接--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 加载mybaties 配置文件 --> <property name="configLocation" value="classpath:mybatisConfig.xml"/> <!-- 自动扫描mapping.xml文件,**表示迭代查找,也可在sqlMapConfig.xml中单独指定xml文件--> <!-- <property name="mapperLocations" value="classpath:com/ssh/sqlmap/*Mapper.xml" /> --> </bean> <!-- spring 注入模板工具类--> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg> </bean>

    <!--                                              方式二,配置事务管理                                                                               -->
         <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>


    <!-- 定义事务的通知 --> 
      <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 指定传播规则 -->

          <tx:attributes> <tx:method name="cre*" read-only="false" propagation="REQUIRED"/>

          <tx:method name="ins*" read-only="false" propagation="REQUIRED"/>

          <tx:method name="upd*" read-only="false" propagation="REQUIRED"/>

          <tx:method name="del*" read-only="false" propagation="REQUIRED"/>

          <tx:method name="*" isolation="DEFAULT" read-only="true" />

      </tx:attributes>

    </tx:advice>


    <!-- 定义一个切面 -->
    <aop:config>
    <!--指定切入的位置-->
          <!-- 切入点:第一个* 代表类型 public private protect 要有空格 切入点表达式的使用规则:
          execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
          有“?”号的部分表示可省略的,modifers-pattern表示修饰符如public、protected等,
          ret-type-pattern表示方法返回类型, declaring-type-pattern代表特定的类,
          name-pattern代表方法名称, param-pattern表示参数,
          throws-pattern表示抛出的异常。在切入点表达式中,可以使用*来代表任意字符,用..来表示任意个参数
    -->

      <aop:pointcut id="bizMethod" expression="execution(* com.ssh.dao.*.*(..))"/>

          <!--将通知和切点编织在一起-->

           <aop:advisor advice-ref="txAdvice" pointcut-ref="bizMethod"/>

      </aop:config>

    </beans>

    方式一或者方式二选择其中一种

    1.采用声明的方式管理事务

    @Transactional(添加事务的传播策略和隔离方式)
    public void transfer(HashMap<String, Object> param) {
    // TODO Auto-generated method stub
    studentDao.updateOutMoney(param);
    studentDao.updateInMoney(param);
    }

    方式二:只要将要调用事务的方法申明为 ins*/upd*/cre*/del*   为前缀的方法即可

    事务没有提交解决办法:

    1.查看配置方式中切面的位置,execution(* com.ssh.dao.*.*(..))"  在dao包下所有类,所有方法前缀为 ins*/upd*/cre*/del* ,才会提交事务

    二:事务的回滚

    事务只有对unchecked 异常才能回滚,所以要分析事务的回滚,先分析异常的分类

    1.Exception 异常时所有异常的父类:包含checked 异常和unchecked 异常

      checked 异常是程序编译的时候显示的异常,要显示的捕获或者抛出,比如:类型强制转化异常

      unchecked  也称为运行时异常,是发生在客户端与服务器端交互的时候,没有能通过代码控制的异常,比如空指针异常,数组下标越界,违法的参数异常,数学异常

        /*
         * 测试事务的回滚
         */
        public void updTransferRollBack(HashMap<String, Object> param) {
            // TODO Auto-generated method stub
                studentDao.updateOutMoney(param);
                
            /*    
             //1.下标越界异常 
              int[] a=new int[3];
                System.out.println(a.length);
                    a[0]=1;
                    a[1]=2;
                    a[2]=3;
                    a[3]=4;
                    System.out.println(a);*/
                //2 空指针异常
                Integer a=null;
                System.out.println(a.toString());
                studentDao.updateInMoney(param);
        }
    //这两种方式都回回滚

    2. 事务的传播策略

      propagation  :

        

    1、Propagation.REQUIRED

    方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。       

      2、Propagation.REQUIRES_NEW

    无论何时自身都会开启事务

      3、Propagation.SUPPORTS

    自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务

      4、Propagation.NOT_SUPPORTED

    自身不会开启事务,在事务范围内使用挂起事务,运行完毕恢复事务

      5、Propagation.MANDATORY

    自身不开启事务,必须在事务环境使用否则报错

      6、Propagation.NEVER

    自身不会开启事务,在事务范围使用抛出异常

      7、Propagation.NESTED

    如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。需要JDBC3.0以上支持。

    测试传播方式

    //测试requred

    public
    void updTransferRollBack(HashMap<String, Object> param) { // TODO Auto-generated method stub studentDao.updateOutMoney(param); /* //1.下标越界异常 int[] a=new int[3]; System.out.println(a.length); a[0]=1; a[1]=2; a[2]=3; a[3]=4; System.out.println(a);*/ //2 空指针异常 /*Integer a=null; System.out.println(a.toString());*/ studentDao.updateInMoney(param);
    //A 测试事务是否回滚
    Integer a=null; System.out.println(a.toString()); updTestRequried(); } public void updTestRequried(){ Random random=new Random(); HashMap<String, Object> param=new HashMap<String, Object>(); param.put("inMoney", random.nextInt()); param.put("id2", "333"); studentDao.updateInMoney(param); }

    结果:当事务的传播方式设置为requred ,
    updTransferRollBack 已经是一个事务,所以 updTestRequried 不用创建一个新的事务,和 updTransferRollBack 方法共用一个事务
    ,所以当在 A 处添加一个RuntimeException 的时候,两个方法里面的sql都会回滚
    
    
  • 相关阅读:
    python瓦登尔湖词频统计
    css规范思维导图(仅限于自己)
    html规范思维导图(仅限于自己)
    vue-cli配置跨域代理
    vue中的scoped分析以及在element-UI和vux中的应用
    yarn和npm的对比,以及项目中使用方式
    Promise对异步编程的贡献以及基本API了解
    跨域限制原因及常见跨域方法
    js中的逗号运算符
    JS中的浅拷贝与深拷贝
  • 原文地址:https://www.cnblogs.com/blogxiao/p/7718891.html
Copyright © 2011-2022 走看看