zoukankan      html  css  js  c++  java
  • Spring事务管理

        springMVC已经越来越流行了。以下是对spring事务的一些个人总结。我们先了解下事务:数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。

      那么在spring框架中怎么使用尼?

      1、dataSource,jdbcTemplate配置(默认已经了解spring)

        <!-- 配置jdbcTemplate -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource" />
        </bean>
        <!-- 配置数据源 -->
        <!-- 以dataSource方式使用proxool连接池 -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" init-method="init" destroy-method="close">
            <property name="name" value="${jdbc.username}" />
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            
            <property name="initialSize" value="${ds.initialSize}" />
            <property name="minIdle" value="${ds.minIdle}" />
            <property name="maxActive" value="${ds.maxActive}" />
            
            <property name="maxWait" value="${ds.maxWait}" />
            <property name="timeBetweenEvictionRunsMillis" value="${ds.timeBetweenEvictionRunsMillis}" />
            <property name="validationQuery" value="SELECT 'x' FROM dual" />
            <property name="connectionProperties" value="oracle.jdbc.ReadTimeout=${oracle.jdbc.ReadTimeout};oracle.net.CONNECT_TIMEOUT=${oracle.net.CONNECT_TIMEOUT}" />
        </bean>

    为了方便修改,采取配置文件的形式。

    # 数据库类型设置(oracle)
    ds.dialect=oracle
    # Oracle数据库
    jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
    jdbc.driver=oracle.jdbc.driver.OracleDriver
    jdbc.username=dreamer
    jdbc.password=123qwe
    # SQL执行时间超过一定时间则记录为慢SQL
    ds.slowSqlMillis=3000
    # 慢SQL统计日志输出
    ds.logSlowSql=false
    # 合并SQL统计
    ds.mergeSql=false
    # 初始化时建立物理连接的个数
    ds.initialSize=1
    # 最小连接数
    ds.minIdle=1
    # 允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 
    ds.maxActive=20
    # 获取连接时最大等待时间
    ds.maxWait=5000
    # 检测需要关闭的空闲连接的间隔时间, 单位是毫秒
    ds.timeBetweenEvictionRunsMillis=120000
    #oracle jdbc驱动socket超时
    oracle.jdbc.ReadTimeout=600000
    #oracle jdbc建立新连接超时时间
    oracle.net.CONNECT_TIMEOUT=6000

    然后就是如果简单的操作数据库了。示例代码

    public class JdbcDemo {
        @Autowired
        public JdbcTemplate jdbcTemplate;
        
        public void callP(){
            //调用存储过程
            jdbcTemplate.execute("{}", new CallableStatementCallback<String>() {
    
                @Override
                public String doInCallableStatement(CallableStatement stat)
                        throws SQLException, DataAccessException {
                    //填参数
                    stat.setString(0, "hello");
                    ResultSet rs = stat.executeQuery();
                    while( rs.next()){
                        rs.getString(0);
                        //....取值
                    }
                    return null;
                }
            });
        }
        public void query(){
            //查询
            jdbcTemplate.query("sql", new RowMapper<Object>(){
    
                @Override
                public Object mapRow(ResultSet rs, int arg1) throws SQLException {
                    rs.getString(0);
                    //.....
                    return null;
                }});
        }
    }

    上面就是spring操作数据库了。此时就涉及到事务管理。如果使用spring事务管理尼。我们可以通过依赖注入@Transactional来使用提醒两个注意点:

    1.只有通过spring方式实例化才有事务。通过new方式实例化将不包含事务
    2.当调用的第一个方法有事务时,里面调用的其他方法也将包含在同一事务里面,反之如果第一个方法没有配置事务,方法内部平级调用方法(此方法配置了事务)。事务也将无效。

    public class Test {
        @Transactional
        public void delData(){
            //有事务
            delTabA();
            //本身配置事务无效,事务类型与delData()一致
            delTabB();
        }
        public void delTabA(){
            
        }
        @Transactional(propagation=Propagation.REQUIRES_NEW)
        public void delTabB(){
            
        }
    }
    class TestDemo{
        @Autowired
        private Test test;
        public void test() {
            //有事务
            test.delData();
            Test test2 = new Test();
            //无事务
            test2.delData();
        }
    }

    3.当方法中抛出异常时,如果声明了抛出异常,事务是不回滚的。如果抛出异常时未检查的。事务将会回滚。
    如果需要回滚需要增加配置@Transactional(rollbackFor=Exception.class)指定异常,可同时配置多个异常

        import org.springframework.transaction.annotation.Transactional;
    
        public class Test2 {
            //出现异常将不会回滚
            @Transactional
            public void test ()throws Exception{
                throw new Exception();
            }
            //将会回滚
            @Transactional(rollbackFor=Exception.class)
            public void test2()throws Exception{
                throw new Exception();
            }
            //将会回滚
            @Transactional
            public void test3(){
                throw new RuntimeException("例外");
            }
    
        }

    通过依赖注入可以选着注入的事务类型 @Transactional(propagation=Propagation.REQUIRES_NEW)

    PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
    PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。 
    PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。 
    PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
    PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
    PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。 
    PROPAGATION_NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

    上面就是对单个方法进行事务控制。适合需要精细化处理的项目。但但部分项目不需要这么精细。就可以通过配置对某个包下方法进行IOC事务配置。

    Stay Hungry,Stay Foolish!
  • 相关阅读:
    【算法】算法的艺术(六)
    【算法】算法·冒泡,选择,插入排序算法
    【算法】算法的应用(一)
    【嵌入式】FS2410非操作系统外围资源测试
    【嵌入式】bootloader,linux,filesystem的烧写
    【Bootloader】bootloader启动过程分析
    【Linux技术】autotools制作makefile过程详解
    【Linux技术】ubuntu常用命令
    【教程】linux下安装Google Chrome
    【电子基础】IIC总线工作原理
  • 原文地址:https://www.cnblogs.com/stay-9527/p/4368181.html
Copyright © 2011-2022 走看看