zoukankan      html  css  js  c++  java
  • Spring_Spring与DAO_Spring的事务管理

    一、Spring的事务管理

         在Spring中通常可以通过以下三种方式来实现对事务的管理:

    1. 使用Spring的事务代理工厂管理事务
    2. 使用Spring的事务注解管理事务
    3. 使用AspectJ的AOP配置管理事务

     二、Spring事务管理API

    (1)事务管理接口

    1、PlatformTransactionManager接口有2个常用的实现类:

    • DataSourceTransactionManager:使用JDBC或者iBatis进行持久化数据时使用;
    • HibernateTransactionManager:使用Hibernate进行持久化数据时使用。

    2、Spring的回滚方式

        Spring事务的默认回滚方式是:发生运行时异常时回滚,发生受查异常时提交。不过对于受查异常,也可以手动设置其回滚方式。

    (2)事务定义接口

    A、5个事务隔离级别

    B、定义了7个事务传播行为常量

    • REQUIRE: 指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中,若当前没有事务,则创建一个新事务。这种传播行为也是最常见的选择,也是Spring默认的事务传播方式;
    • SUPPORTS:指定的方法支持支持当前事务,但若当前没有事务,也可以以非事务方式执行;
    • MANDATORY:指定的方法必须在当前事务内执行,若当前没有事务,则直接抛出异常;
    • REQUIRES_NES:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕;
    • NOT_SUPPORTED:指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起‘
    • NEVER:指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常;
    • NESTED:指定的方法必须在事务内执行,若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务;

     c、默认事务超时时限

    三、程序举例环境搭建

    购买股票举例


    1、定义实体类及DB表

     1 public class Account {
     2     private Integer aid;
     3     private String aname;
     4     private double balance;// 余额
     5     
     6     
     7     public Account() {
     8         super();
     9     }
    10 
    11 
    12     public Account(Integer aid, String aname, double balance) {
    13         super();
    14         this.aid = aid;
    15         this.aname = aname;
    16         this.balance = balance;
    17     }
    18 
    19 
    20     public Integer getAid() {
    21         return aid;
    22     }
    23 
    24 
    25     public void setAid(Integer aid) {
    26         this.aid = aid;
    27     }
    28 
    29 
    30     public String getAname() {
    31         return aname;
    32     }
    33 
    34 
    35     public void setAname(String aname) {
    36         this.aname = aname;
    37     }
    38 
    39 
    40     public double getBalance() {
    41         return balance;
    42     }
    43 
    44 
    45     public void setBalance(double balance) {
    46         this.balance = balance;
    47     }
    48 
    49 
    50     @Override
    51     public String toString() {
    52         return "Account [aid=" + aid + ", aname=" + aname + ", balance=" + balance + "]";
    53     }
    54     
    55     
    56 }
    Account
     1 public class Stock {
     2     private Integer sid;
     3     private String sname;// 股票名称
     4     private int count;// 股票数量
     5     
     6     public Stock() {
     7         super();
     8     }
     9 
    10     public Stock(Integer sid, String sname, int count) {
    11         super();
    12         this.sid = sid;
    13         this.sname = sname;
    14         this.count = count;
    15     }
    16 
    17     public Integer getSid() {
    18         return sid;
    19     }
    20 
    21     public void setSid(Integer sid) {
    22         this.sid = sid;
    23     }
    24 
    25     public String getSname() {
    26         return sname;
    27     }
    28 
    29     public void setSname(String sname) {
    30         this.sname = sname;
    31     }
    32 
    33     public int getCount() {
    34         return count;
    35     }
    36 
    37     public void setCount(int count) {
    38         this.count = count;
    39     }
    40 
    41     @Override
    42     public String toString() {
    43         return "Stock [sid=" + sid + ", sname=" + sname + ", count=" + count + "]";
    44     }
    45 
    46     
    47     
    48 }
    Stock

    二、定义Service

    1 public interface IBuyStockService {
    2    void openAccount(String aname,double money);//开用户
    3    void openStock(String sname,int amount);
    4    
    5    void buyStock(String aname,double money,String sname,int amount) throws BuyStockException;
    6 }
    IBuyStockService
     1 import com.jmu.dao.IAccountDao;
     2 import com.jmu.dao.IStockDao;
     3 
     4 public class BuyStockService implements IBuyStockService {
     5     private IAccountDao adao;
     6     private IStockDao sdao;
     7 
     8     public void setAdao(IAccountDao adao) {
     9         this.adao = adao;
    10     }
    11 
    12     public void setSdao(IStockDao sdao) {
    13         this.sdao = sdao;
    14     }
    15 
    16     @Override
    17     public void openAccount(String aname, double money) {
    18         // TODO Auto-generated method stub
    19         adao.insertAccount(aname, money);
    20     }
    21 
    22     @Override
    23     public void openStock(String sname, int amount) {
    24         // TODO Auto-generated method stub
    25         sdao.insertStock(sname, amount);
    26     }
    27 
    28     @Override
    29     public void buyStock(String aname, double money, String sname, int amount) throws BuyStockException {
    30         // TODO Auto-generated method stub
    31         boolean isBuy = true;
    32         adao.updateAccount(aname, money, isBuy);
    33 
    34         if (1 == 1) {
    35             throw new BuyStockException("购买股票异常");
    36         }
    37         sdao.updateStock(sname, amount, isBuy);
    38 
    39     }
    40 
    41 }
    BuyStockService
     1 public class BuyStockException extends Exception {
     2 
     3     public BuyStockException() {
     4         super();
     5         // TODO Auto-generated constructor stub
     6     }
     7 
     8     public BuyStockException(String message) {
     9         super(message);
    10         // TODO Auto-generated constructor stub
    11     }
    12 
    13 }
    BuyStockException

    三、定义Dao 

    1 public interface IAccountDao {
    2 
    3      void insertAccount(String aname, double money);
    4      void updateAccount(String aname, double money, boolean isBuy);
    5      
    6 
    7 }
    IAccountDao
    1 public interface IStockDao {
    2 
    3     void insertStock(String sname, int amount);
    4     void updateStock(String sname, int amount, boolean isBuy);
    5 
    6 }
    IStockDao
     1 import org.springframework.jdbc.core.support.JdbcDaoSupport;
     2 
     3 public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
     4 
     5     @Override
     6     public void insertAccount(String aname, double money) {
     7         // TODO Auto-generated method stub
     8         String sql = "insert into account(aname,balance) values(?,?)";
     9         this.getJdbcTemplate().update(sql, aname, money);
    10     }
    11 
    12     @Override
    13     public void updateAccount(String aname, double money, boolean isBuy) {
    14         String sql = "update account set balance=balance+? where aname=?";
    15         if (isBuy) {
    16             // TODO Auto-generated method stub
    17             sql = "update account set balance=balance-? where aname=?";
    18         }
    19         this.getJdbcTemplate().update(sql, money,aname);
    20     }
    21 
    22 }
    AccountDaoImpl
     1 import org.springframework.jdbc.core.support.JdbcDaoSupport;
     2 
     3 public class StockDaoImpl extends JdbcDaoSupport implements IStockDao {
     4 
     5     @Override
     6     public void insertStock(String sname, int amount) {
     7         // TODO Auto-generated method stub
     8         String sql="insert into stock(sname,count) values(?,?)";
     9         this.getJdbcTemplate().update(sql,sname,amount);
    10     }
    11 
    12     @Override
    13     public void updateStock(String sname, int amount, boolean isBuy) {
    14         // TODO Auto-generated method stub
    15         String sql="update stock set count=count-? where sname=?";
    16         if (isBuy) {
    17             sql="update stock set count=count+? where sname=?";
    18         }
    19         this.getJdbcTemplate().update(sql,amount,sname);
    20     };
    21 
    22 }
    StockDaoImpl

    四、导入Jar包

    项目结构


    五、使用事务代理管理事务(方法一)

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
     4     xsi:schemaLocation="
     5         http://www.springframework.org/schema/beans 
     6         http://www.springframework.org/schema/beans/spring-beans.xsd
     7         http://www.springframework.org/schema/context 
     8         http://www.springframework.org/schema/context/spring-context.xsd">
     9 <!-- IoC -->
    10     
    11     <!--注册数据源:C3P0 -->
    12     <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    13         <property name="driverClass" value="${jdbc.driver}" />
    14         <property name="jdbcUrl" value="${jdbc.url}" />
    15         <property name="user" value="${jdbc.user}" />
    16         <property name="password" value="${jdbc.password}" />
    17     </bean>
    18     
    19    <!--  注册属性文件 -->
    20    <context:property-placeholder location="classpath:jdbc.properties"/>
    21    <!--注册Dao -->
    22     <bean id="accountDao" class="com.jmu.dao.AccountDaoImpl">
    23         <property name="dataSource" ref="myDataSource" />
    24 
    25     </bean>
    26     <bean id="stockDao" class="com.jmu.dao.StockDaoImpl">
    27         <property name="dataSource" ref="myDataSource" />
    28 
    29     </bean>
    30 
    31     <!-- 注册Service -->
    32     <bean id="buyStockService" class="com.jmu.service.BuyStockService">
    33         <property name="adao" ref="accountDao" />
    34         <property name="sdao" ref="stockDao"/>
    35     </bean>
    36     
    37     
    38     <!-- AOP -->
    39     <!-- 注册事务管理器 -->
    40     <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    41        <property name="dataSource" ref="myDataSource"></property>
    42     </bean>
    43     
    44     <!-- 生成事务代理对象 -->
    45     <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    46        <property name="transactionManager" ref="myTransactionManager"></property>
    47        <property name="target" ref="buyStockService"></property>
    48        <property name="transactionAttributes">
    49           <props>
    50             <prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
    51             <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException </prop>
    52             <!-- 
    53                 -异常:表示发生指定异常后 回滚 (通常是受查异常)
    54                 +异常:表示发生指定异常后提交 (通常是运行时异常)
    55             -->
    56           </props>
    57        </property>
    58     </bean>
    59 </beans>
    applicationContext.xml

    -异常:表示发生指定异常后 回滚 (通常是受查异常)
    +异常:表示发生指定异常后提交 (通常是运行时异常)

    <!-- 生成事务代理对象 -->
        <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
           <property name="transactionManager" ref="myTransactionManager"></property>
           <property name="target" ref="buyStockService"></property>
           <property name="transactionAttributes">
              <props>
                <prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
                <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException </prop>
                <!-- 
                    -异常:表示发生指定异常后 回滚 (通常是受查异常)
                    +异常:表示发生指定异常后提交 (通常是运行时异常)
                -->
              </props>
           </property>
        </bean>
     1 import org.junit.Before;
     2 import org.junit.Test;
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.support.ClassPathXmlApplicationContext;
     5 
     6 import com.jmu.service.BuyStockException;
     7 import com.jmu.service.IBuyStockService;
     8 
     9 public class MyTest {
    10 
    11      private IBuyStockService service;
    12      
    13      @Before
    14      public void before(){
    15          String resource="applicationContext.xml";
    16          ApplicationContext aContext=new ClassPathXmlApplicationContext(resource);
    17          service=(IBuyStockService)aContext.getBean("serviceProxy");
    18      }
    19   
    20      @Test
    21      public void test01(){
    22          service.openAccount("张三", 10000);
    23          service.openStock("腾讯", 0);
    24          
    25      }
    26      @Test
    27      public void test02() throws BuyStockException{
    28          service.buyStock("张三", 2000, "腾讯", 5);
    29          
    30          
    31      }
    32     
    33     
    34 }
    MyTest

    六、使用注解管理事务(方法二)

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

        <!-- AOP -->
        <!-- 注册事务管理器 -->
        <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
           <property name="dataSource" ref="myDataSource"></property>
        </bean>
        
        <!-- 注册事务注解驱动 -->
        <tx:annotation-driven transaction-manager="myTransactionManager"/>   
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
        @Override
        public void openAccount(String aname, double money) {
            // TODO Auto-generated method stub
            adao.insertAccount(aname, money);
        }
    
        @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
        @Override
        public void openStock(String sname, int amount) {
            // TODO Auto-generated method stub
            sdao.insertStock(sname, amount);
        }
    
        @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED,rollbackFor=BuyStockException.class)
        @Override
        public void buyStock(String aname, double money, String sname, int amount) throws BuyStockException {
            // TODO Auto-generated method stub
            boolean isBuy = true;
            adao.updateAccount(aname, money, isBuy);
    
            if (1 == 1) {
                throw new BuyStockException("购买股票异常");
            }
            sdao.updateStock(sname, amount, isBuy);
    
        }

    输出结果:

    七、使用AspectJ的AOP配置管理事务(重点)

    导入Jar包

    <!-- AOP -->
        <!-- 注册事务管理器 -->
        <bean id="myTransactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="myDataSource"></property>
        </bean>
    
        <tx:advice id="txAdvice" transaction-manager="myTransactionManager">
            <!--事务属性 -->
            <!--将事务属性织入到方法中 -->
            <tx:attributes>
                <!--这里指定的是为每一个连接点指定所要应用的事务属性 -->
                <tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED" />
                <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED"
                    rollback-for="BuyStockException" />
            </tx:attributes>
        </tx:advice>
    
        <!-- AOP配置 -->
        <aop:config>
            <!--这里指定的是切入点 -->
            <!-- execution(* *..service.*.open*(..)) -->
            <aop:pointcut expression="execution(* *..service.*.*(..))"
                id="myPoint" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint" />
        </aop:config>
    View Code
  • 相关阅读:
    C#执行异步操作的几种方式
    spring boot swagger ui使用 nginx 部署后无法使用问题
    PHP支付宝接口RSA验证
    认证加密算法php hash_hmac和java hmacSha1的问题
    如何实现从 Redis 中订阅消息转发到 WebSocket 客户端
    ffmpeg安装
    nginx静态资源反向代理
    Redis基础知识 之——发布/订阅
    linux下安装git
    php实现无限级分类查询(递归、非递归)
  • 原文地址:https://www.cnblogs.com/hoje/p/8484125.html
Copyright © 2011-2022 走看看