zoukankan      html  css  js  c++  java
  • 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();

  • 相关阅读:
    科学计算——笔记
    Python_scrapyRedis零散
    Python博文_爬虫工程师是干什么的
    [单选题]怎样打开或创建一个文件?
    [问答题] 写出一个正则表达式,过虑网页上的所有JS/VBS脚本(即把script标记及其内容都去掉):
    [单选题]<?php$age =18;$age?$age+10:$age+20;echo $age;?>
    [单选题]有关PHP面向对象的说法,不对的是:
    [单选题]要循环操作非顺序索引的数组时,可以用下面哪个函数来读取数组当面元素的索引值?
    [单选题]PHP中定义常量的方法是:
    [单选题]stdClass的一个对象如何设置成员value的值?
  • 原文地址:https://www.cnblogs.com/SacredOdysseyHD/p/8592469.html
Copyright © 2011-2022 走看看