• Spring--事务管理


    1、通常在java ee编程中,有两种事务管理的方式:全局事务和本地事务。

      全局事务:可以同时管理多个transaction,但是通常都需要依赖于容器的事务管理

      本地事务:直接使用jdbc的事务管理但是不能同时管理多个事务 

    2、但是在spring的事务管理中,它解决了全局事务和本地事务的缺点,它是的程序员可以在任何开发环境中都使用一致的编程模式,而且不依赖与任何的事务管理api。spring提供了声明式事务管理(推荐使用)和编程式事务管理。

    spring的事务抽象中,依赖的最重要的一个类就是:org.springframework.transaction.PlatformTransactionManager接口

    public interfact PlatformTransactionManager{
        
        TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
        
        void commit(TransactionStatus status) throws TransactionException;
        
        void rollback(TransactionStatus status) throws TransactionException;p
    }

    这是一个最基本的服务提供接口(SPI)。

    getTransaction()方法依赖于一个TransactionDefinition类型的参数,返回一个TransactionStatus类型的对象,返回的TransactionStatus可以是一个新的transaction也有可能是一个已存的transaction。一个TransactionStatus总是和一个线程的执行相关联的。

    TransactionDefinition接口指明了以下内容:

    Isolation(隔离性):当前事务和其他事务是隔离开的

    Propagation(传播):通常在事务范围里面执行的代码都会在这个事务里执行,但是,当一个事务已经存在的时候,你可以选择指定在事务方法被执行的事件中的行为,例如:代码可以在已存的事务中持续执行,或者已存的事务可以被挂起,然后一个创建一个新的事务。

    Timeout(持久性):当前事务执行多久结束或者自动回滚

    Read-only status(只读):但你的代码只是读操作,并没有对数据做修改的时候,就可以选择使用只读事务,只读事务操作在使用hibernate之类的情况下会是一个最佳的优化。

    TransactionStatus接口提供了一种简单的方式去控制事务的执行和查询事务状态

    public interface TransactionStatus extends SavepointManager {
    
        boolean isNewTransaction();
    
        boolean hasSavepoint();
    
        void setRollbackOnly();
    
        boolean isRollbackOnly();
    
        void flush();
    
        boolean isCompleted();
    
    }

    不论使用声明式事务管理还是编程式事务管理,都需要正确的实现PlatformTransactionManager接口,通常都是通过依赖注入来实现。

    下面是一种使用最基本的JDBC来实现本地PlatformTransactionManager的例子。

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    相关联的PlatformTransactionManager类的定义需要注入一个dataSource

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    当你使用Java EE容器中的JTA的时候,你可以使用容器的DataSource,下面是一个使用JTA和JNDI的例子:

    <?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:jee="http://www.springframework.org/schema/jee"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/jee
            http://www.springframework.org/schema/jee/spring-jee.xsd">
    
        <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
    
        <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    
        <!-- other <bean/> definitions here -->
    
    </beans>

    JtaTransactionManager不需要知道DataSource,或者其他特定的资源,因为它使用的是容器的全局事务管理结构。

    你也可以更简单使用Hibernate的本地事务管理,但是你需要定义一个hibernate的LocalSessionFactoryBean,用来实例化Hibernate的Session实例。

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingResources">
            <list>
                <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${hibernate.dialect}
            </value>
        </property>
    </bean>
    
    <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    3、事务中的资源同步

    ①高级同步实现

      首选的实现是使用spring的最高级模板。这个模板是基于持久综合APIs或者使用本地的ORM APIs和食物通知工厂类或者代理。通常使用JdbcTemplate来实现。

    ②低级同步实现

      像DataSourceUtils(JDBC用),EntityManagerFactoryUtils(JPA用),SessionFactoryUtils(Hibernate用)PersistenceManagerFactoryUtils(JDO用)等等之类的既存的低级事务管理类。当你想程序代码直接处理本地持久APIs资源类型的时候,你可以使用这些类来保证获得合适的Spring Framework-Managed实例。

    例如:在JDBC的时候,使用Spring的org.springframework.jdbc.datasource.DataSourceUtils类来代理传统的JDTC调用getConnection()方法来实现

    Connection conn = DataSourceUtils.getConnection(dataSource);

    当已经存在一个相关联的同步连接的时候,那么这个连接会被返回,否则的话则会返回一个新的连接。

    ③TransactionAwareDataSourceProxy

      在很底层存在一个TransactionAwareDataSourceProxy类,这是一个DataSource的代理类,对DataSource类实行了一个包装并且加了一个对Spring管理的事务的认识。

      通常我们都不需要使用这个类,除了既存的代码必须调用并且传递一个标准的DataSource接口实现。

    4、声明式事务管理

    下面是一个实现转账的具体实例:

    表结构定义:

    package com.fuwh.dao;
    
    //定义一个出入帐的接口类
    public interface MoneyDao {
        
        public abstract void inMoney(int money,int id);
        
        public abstract void outMoney(int money,int id);
    
        
    }
     1 package com.fuwh.dao.impl;
     2 
     3 import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
     4 import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
     5 
     6 import com.fuwh.dao.MoneyDao;
     7 
     8 //出入帐接口类的具体实现类
     9 public class MoneyDaoImpl implements MoneyDao{
    10 
    11     private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    12     
    13     public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
    14         this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    15     }
    16 
    17     @Override
    18     public void inMoney(int money,int id) {
    19         // TODO Auto-generated method stub
    20         String sql="update t_money set money=money+:money where id=:id";
    21         MapSqlParameterSource msps=new MapSqlParameterSource("money", money);
    22         msps.addValue("id", id);
    23         namedParameterJdbcTemplate.update(sql, msps);
    24     }
    25 
    26     @Override
    27     public void outMoney(int money,int id) {
    28         // TODO Auto-generated method stub
    29         String sql="update t_money set money=money-:money where id=:id";
    30         MapSqlParameterSource msps=new MapSqlParameterSource("money",money);
    31         msps.addValue("id", id);
    32         namedParameterJdbcTemplate.update(sql, msps);
    33     }
    34 
    35 }
    package com.fuwh.Service;
    
    //定义一个转账服务类
    public interface MoneyService {
    
        public void transferMoney(int money,int inId,int outId);
    }
     1 package com.fuwh.Service.impl;
     2 
     3 import com.fuwh.dao.MoneyDao;
     4 import com.fuwh.Service.MoneyService;
     5 
     6 //转账服务类的具体实现
     7 public class MoneyServiceImpl implements MoneyService {
     8 
     9     private MoneyDao moneyDao;
    10     
    11     public void setMoneyDao(MoneyDao moneyDao) {
    12         this.moneyDao = moneyDao;
    13     }
    14 
    15     @Override
    16     public void transferMoney(int money, int inId, int outId) {
    17         // TODO Auto-generated method stub
    18         moneyDao.outMoney(money, outId);
    19         moneyDao.inMoney(money, inId);
    20     }
    21 
    22 }
    package com.fuwh.test;
    
    import org.junit.Before;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.fuwh.Service.MoneyService;
    
    //Junit测试类
    public class Test {
    
        private ApplicationContext ac;    
    
        @Before
        public void setUp() throws Exception {
            ac=new ClassPathXmlApplicationContext("beans.xml");
        }
    
        @org.junit.Test
        public void testTransfer() {
            MoneyService md=(MoneyService)ac.getBean("moneyService");
            md.transferMoney(50, 1, 2);
        }
    }
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 
     3 <beans xmlns="http://www.springframework.org/schema/beans"
     4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     5     xmlns:aop="http://www.springframework.org/schema/aop"
     6     xmlns:context="http://www.springframework.org/schema/context"
     7     xmlns:tx="http://www.springframework.org/schema/tx"
     8     xsi:schemaLocation="http://www.springframework.org/schema/beans
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/aop
    11         http://www.springframework.org/schema/aop/spring-aop.xsd
    12         http://www.springframework.org/schema/context
    13         http://www.springframework.org/schema/context/spring-context.xsd
    14         http://www.springframework.org/schema/tx
    15         http://www.springframework.org/schema/tx/spring-tx.xsd">
    16 
    17     <!-- 配置DataSource
    18          这里使用的是apache的dbcp连接池
    19          需要引入apache的dbcp连接池jarbao
    20          commons-dbcp2-2.1.1.jar 和 commons-pool2-2.4.2.jar
    21      -->    
    22     <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    23         <property name="driverClassName" value="${jdbc.driverClassName}"/>
    24         <property name="url" value="${jdbc.url}"/>
    25         <property name="username" value="${jdbc.username}"/>
    26         <property name="password" value="${jdbc.password}"/>
    27     </bean>
    28 
    29     <context:property-placeholder location="jdbc.properties"/>
    30 
    31     <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    32         <constructor-arg ref="dataSource"></constructor-arg>
    33     </bean>
    34     <bean id="moneyDao" class="com.fuwh.dao.impl.MoneyDaoImpl">
    35         <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
    36     </bean>
    37     <bean id="moneyService" class="com.fuwh.Service.impl.MoneyServiceImpl">
    38         <property name="moneyDao" ref="moneyDao"></property>
    39     </bean>
    40     
    41     <!-- 声明所有的方法都使用默认的事务定义 -->
    42     <tx:advice id="txAdvice" transaction-manager="txManager">
    43         <tx:attributes>
    44             <tx:method name="*"/>
    45         </tx:attributes>
    46     </tx:advice>
    47 
    48     <aop:config>
    49         <aop:pointcut id="txPoint" expression="execution(* com.fuwh.Service.*.*(..))" />
    50         <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
    51     </aop:config>
    52     
    53     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    54         <property name="dataSource" ref="dataSource"></property>
    55     </bean>
    56     
    57 </beans>
    #jdbc连接配置属性文件
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/db_spring
    jdbc.username=root
    jdbc.password=mysqladmin

    5、编程式事务管理

    在spring中提供了两种方式来实现编程式事务管理

      |-使用TransactionTemplate(推荐使用)

      |-使用PlatformTransaxtionManager实现

    具体实现实例:

     1 package com.fuwh.Service.impl;
     2 
     3 import com.fuwh.dao.MoneyDao;
     4 
     5 import org.springframework.transaction.TransactionStatus;
     6 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
     7 import org.springframework.transaction.support.TransactionTemplate;
     8 
     9 import com.fuwh.Service.MoneyService;
    10 
    11 //转账服务类的具体实现
    12 public class MoneyServiceImpl implements MoneyService {
    13 
    14     private TransactionTemplate transactionTemplate;
    15 
    16     public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    17         this.transactionTemplate = transactionTemplate;
    18     }
    19 
    20     private MoneyDao moneyDao;
    21     
    22     public void setMoneyDao(MoneyDao moneyDao) {
    23         this.moneyDao = moneyDao;
    24     }
    25 
    26     @Override
    27     public void transferMoney(final int money, final int inId, final int outId) {
    28         // TODO Auto-generated method stub
    29         transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    30                         
    31             @Override
    32             protected void doInTransactionWithoutResult(TransactionStatus status) {
    33                 // TODO Auto-generated method stub
    34                 moneyDao.outMoney(money, outId);
    35                 moneyDao.inMoney(money, inId);
    36             }
    37         });
    38     }
    39 
    40 }
    <?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:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!-- 配置DataSource
             这里使用的是apache的dbcp连接池
             需要引入apache的dbcp连接池jarbao
             commons-dbcp2-2.1.1.jar 和 commons-pool2-2.4.2.jar
         -->    
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
    
        <context:property-placeholder location="jdbc.properties"/>
    
        <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
            <constructor-arg ref="dataSource"></constructor-arg>
        </bean>
        <bean id="moneyDao" class="com.fuwh.dao.impl.MoneyDaoImpl">
            <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
        </bean>
        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="txManager"></property>
        </bean>
        
        <bean id="moneyService" class="com.fuwh.Service.impl.MoneyServiceImpl">
            <property name="moneyDao" ref="moneyDao"></property>
            <property name="transactionTemplate" ref="transactionTemplate"></property>
        </bean>
        
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        
    </beans>

    6、<tx:advice>配置详解

    默认的<tx:advice>是:

    传播(propagation):REQUIRED

    隔离(Isolation):DEFAULT

    事务(Transaction):read/write

    持久性(timeout):默认的timeout是底层的事务系统

    例如:

    <tx:advice id="txAdvice" transaction-manager="txManager" >
            <tx:attributes>
                <tx:method name="*" />
            </tx:attributes>
        </tx:advice>

    在<tx:method>标签中,可以加入以下的配置来更改默认的设置

    属性 必须? 默认 描述
    name 必须   匹配的方法,*:所有的方法,get*:以get开头的方法等等
    propagation 非必须 REQUIRED 食物传播行为
    isolation 非必须 DEFAULT 事务隔离等级
    timeout 非必须 -1 timeout的时间(秒单位)
    read-only 非必须 false 是否只读
    rollback-for 非必须   rollback的时候执行的方法
    no-rollback-for 非必须   没有触发rollback的时候执行的方法



  • 相关阅读:
    paper 30 :libsvm的参数说明
    paper 29 :CV会议+领先研究室+专家+代码网址
    paper 28 :一些常见常用数据库的下载网站集锦
    paper 27 :图像/视觉显著性检测技术发展情况梳理(Saliency Detection、Visual Attention)
    paper 25 :SVM支持向量机是什么意思?
    paper 24 :matlab的cat函数
    paper 23 :Kullback–Leibler divergence KL散度(2)
    paper 22:kl-divergence(KL散度)实现代码
    paper 21 :Libsvm的安装和使用
    paper 20 :color moments
  • 原文地址:https://www.cnblogs.com/zerotomax/p/6285342.html
Copyright © 2020-2023  润新知