spring 事务控制

事务控制的分类

  一、编程式事务控制  

  自己手动控制事务,就叫做编程式事务控制。

         Jdbc代码:

                   Conn.setAutoCommite(false);  // 设置手动控制事务

         Hibernate代码:

                   Session.beginTransaction();    // 开启一个事务

         【细粒度的事务控制: 可以对指定的方法、指定的方法的某几行添加事务控制】

         (比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚.)

  代码演示

  (1)数据库创建表 user (只有 name age 两个字段)

  (2)spring 配置文件

<?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:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <!-- 开启注解 -->
    <context:component-scan base-package="com.ant"></context:component-scan>
    <!-- 1. 数据源对象: C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/demo" />
        <property name="user" value="root" />
        <property name="password" value="123456" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="dataSourceTransactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

 

   (3)定义事务管理类

  

  (4)简单定义了  User 、UserDao 

  

  

  (5)UserService

package com.ant.service;
/**
 * 手动管理事务
 */
@Service
public class UserService {
    
    @Autowired
    private UserDao userDao; 
    

    //事务管理的类
    @Autowired
    private MyTransaction myTransaction;
    
    public void add(){
        TransactionStatus transaction = myTransaction.begin();
        userDao.insert("zhansan1111", 12);
        int i = 12/0;
        myTransaction.commit(transaction);
        /*
        (1)没有开启事务时,程序执行到 i = 12/0  
            数据库已经成功保存了该数据
        (2)开启事务时,i = 12/0 报错后
            程序将不会执行到 commit 进行对数据事务提交
            因此,数据库无该数据
        (3)开启事务的同时对 i = 12/0 进行 try catch 
            那么程序将执行到 commit ,故此应该在 cath 块中
            执行 rollback 
            
            try {
            int i = 12/0;
        } catch (Exception e) {
            myTransaction.rollback(transaction);
            e.printStackTrace();
        }
        */
    }
    
}

  (6)测试代码

  

  二、声明式事务控制

         Spring提供了对事务的管理, 这个就叫声明式事务管理。

         Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可; 不想使用时直接移除配置。这个实现了对事务控制的最大程度的解耦。

         Spring声明式事务管理,核心实现就是基于Aop。

         【粗粒度的事务控制: 只能给整个方法应用事务,不可以对方法的某几行应用事务。】

         (因为aop拦截的是方法。)

         Spring声明式事务管理器类:

                   Jdbc技术:DataSourceTransactionManager

                   Hibernate技术:HibernateTransactionManager

   (一) XML方式实现  沿用上面的代码

    (1)spring 配置文件配置

<?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:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


    <!-- 开启注解 -->
    <context:component-scan base-package="com.ant"></context:component-scan>
    <!-- 1. 数据源对象: C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/demo" />
        <property name="user" value="root" />
        <property name="password" value="123456" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="dataSourceTransactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置事物增强 -->
    <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
        <tx:attributes>
        <!-- 常见的默认配置 read-only : 只读-->
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="*" read-only="false" />
        </tx:attributes>
    </tx:advice>
    <!-- Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
    <aop:config>
        <aop:pointcut expression="execution(* com.ant.service.*.*(..))"
            id="pt" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
    </aop:config>

</beans>

  (2)测试的方法

  只是在之前的测试方法中进行方法调用

  

  (二) 注解方式实现  沿用上面的代码

  (1)spring xml 文件只需要简单的配置(数据源、事务管理器、开启事务注解)

  <!-- 配置事务管理器 -->
    <bean id="dataSourceTransactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 开启事务注解,注意:注解扫描包的位置 -->
     <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

  (2)再在对应的方法上进行注解  @Transactional

  

 

  只需这样简单的配置就等价于 xml 的实现。

注意:

 事物是程序运行如果没有错误,会自动提交事物,如果程序运行发生异常,则会自动回滚。

 如果使用了try捕获异常时.一定要在catch里面手动回滚。

 事物手动回滚代码

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

posted @ 2018-03-17 20:22  TigerExpensive  阅读(269)  评论(0编辑  收藏  举报