zoukankan      html  css  js  c++  java
  • spring tranaction 事务入门

    一、事务四个属性

    原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
    一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
    隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
    持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

    二、事务的重要性

    打个最简单的比方吧,A和B两人之间的支付宝转账问题,A向B转账50RMB,正常的结果是,A - 50 并且 B + 50; 但如果是下面这种情况,那就杯具了,A - 50 成功,而B + 50 失败。这样一来岂不是 A亏大了!谁还敢随意转账?就算是首富,也不敢随意转账O(∩_∩)O哈!

    所以,在进行 A - 50 和 B + 50 需要添加事务管理。

    三、先看下没有加事务的Demo, 看完就知道事务的重要性啦~

    (1)、整体结构、

     

    (2)、jar 包

    (3)、SQL语句

    创建数据库
    
    create database spring;
    
    建立表
    
    create table countmoney(idCard int primary key auto_increment,name varchar(32),money int);
    
    插入两条记录
    
    insert into countmoney(name,money)values('xx',300);
    insert into countmoney(name,money)values('++',300);

    结果

     select * from countmoney; 

    +--------+------+-------+
    | idCard | name | money |
    +--------+------+-------+
    | 1 | xx | 300 |
    | 2 | ++ | 300 |
    +--------+------+-------+

    (4)、代码

    model 层

     1 package com.xpw.model;
     2 
     3 public class Count {
     4     private int idCard;
     5     private String name;
     6     private int money;
     7     
     8     public Count(){
     9         
    10     }
    11     
    12     public int getIdCard() {
    13         return idCard;
    14     }
    15     public void setIdCard(int idCard) {
    16         this.idCard = idCard;
    17     }
    18     public String getName() {
    19         return name;
    20     }
    21     public void setName(String name) {
    22         this.name = name;
    23     }
    24     public int getMoney() {
    25         return money;
    26     }
    27     public void setMoney(int money) {
    28         this.money = money;
    29     }
    30     
    31 }
    View Code

    dao 层

    1 package com.xpw.dao;
    2 
    3 public interface TradeDao {
    4 
    5     public void outputMoney(int idCard, int money);
    6     
    7     public void inputMoney(int idCard, int money);
    8 }
    View Code

    dao impl 层

     1 package com.xpw.dao.impl;
     2 
     3 import org.springframework.jdbc.core.JdbcTemplate;
     4 import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
     5 import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
     6 import org.springframework.jdbc.core.namedparam.SqlParameterSource;
     7 
     8 import com.xpw.dao.TradeDao;
     9 
    10 public class TradeDaoImpl implements TradeDao {
    11 
    12     private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    13 
    14     public void setNamedParameterJdbcTemplate(
    15             NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
    16         this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    17     }
    18 
    19     @Override
    20     public void outputMoney(int idCard, int count) {
    21         String sql = "update trademoney set money = money -:count where idCard = :idCard";
    22         MapSqlParameterSource param = new MapSqlParameterSource();
    23         param.addValue("count", count);
    24         param.addValue("idCard", idCard);
    25         this.namedParameterJdbcTemplate.update(sql, param);
    26     }
    27 
    28     @Override
    29     public void inputMoney(int idCard, int count) {
    30         //我们故意在此出错,抛出异常,让 B + 50失败
    31         System.out.println(1/0);
    32         String sql = "update trademoney set money = money + :count where idCard = :idCard";
    33         MapSqlParameterSource param = new MapSqlParameterSource();
    34         param.addValue("count", count);
    35         param.addValue("idCard", idCard);
    36         this.namedParameterJdbcTemplate.update(sql, param);
    37     }
    38 }
    View Code

    Service层

    1 package com.xpw.service;
    2 
    3 public interface TradeService {
    4     public void trade(int fromIdCard, int toIdCard, int money);
    5 }
    View Code

    Service impl 层

     1 package com.xpw.service.impl;
     2 
     3 import com.xpw.dao.TradeDao;
     4 import com.xpw.service.TradeService;
     5 
     6 public class TradeServiceImpl implements TradeService {
     7     
     8     private TradeDao tradeDao;
     9     
    10     public void setTradeDao(TradeDao tradeDao) {
    11         this.tradeDao = tradeDao;
    12     }
    13     
    14     @Override
    15     public void trade(int fromIdCard, int toIdCard, int money) {
    16         this.tradeDao.outputMoney(fromIdCard, money);
    17         this.tradeDao.inputMoney(toIdCard, money);
    18     }
    19 }
    View Code

    (5)文件配置信息

    beans.xml

     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"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="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     
    10     <context:component-scan base-package="org.springframework.docs.test" />
    11     <context:property-placeholder location="jdbc.properties"/>    
    12     
    13     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    14         <property name="driverClassName" value="${jdbc.driverClassName}"/>
    15         <property name="url" value="${jdbc.url}"/>
    16         <property name="username" value="${jdbc.username}"/>
    17         <property name="password" value="${jdbc.password}"/>
    18     </bean>
    19 
    20     <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    21         <constructor-arg ref="dataSource"></constructor-arg>
    22     </bean>
    23 
    24     <bean id="tradeDao" class="com.xpw.dao.impl.TradeDaoImpl">
    25         <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/>
    26     </bean>
    27 
    28     <bean id="tradeService" class="com.xpw.service.impl.TradeServiceImpl">
    29         <property name="tradeDao" ref="tradeDao"></property>
    30     </bean>
    31 </beans>
    View Code

    jdbc.properties

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/spring
    jdbc.username=root
    jdbc.password=root

    (6)测试

    package com.xpw.trade;
    
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.xpw.service.TradeService;
    
    
    public class TradeTest {
        
        private static ApplicationContext ac;
        
        @Before
        public void init(){
            ac = new ClassPathXmlApplicationContext("beans.xml");
        }
        
        @Test
        public void testTrade(){
            TradeService ts = (TradeService) ac.getBean("tradeService");
            int fromIdCard = 1;
            int toIdCard = 2;
            int money = 50;
            ts.trade(fromIdCard, toIdCard, money);
        }
    }
    结果
    
    select * from trademoney;
    
    +--------+------+-------+
    | idCard | name | money |
    +--------+------+-------+
    |      1 | xx   |   250 |
    |      2 | ++   |   300 |
    +--------+------+-------+
    2 rows in set (0.00 sec)
    
    由于,在 inputmoney()方法,我们故意 做1/0操作,也没有做try catch ,导致不会往下执行向B账户添加50的业务,所以 A亏了50。。。
    
    从上面的结果我们知道了事务的重要性了吧。。A - 50 和 B + 50 必须同时成功,才可以称为一个成功的交易,一旦 谁出错,就必须回滚!即 不能 将 A - 50 , B 也不能 被 + 50

    下面,我们就 添加事务管理吧。。当然,事务管理有两种,详情见如下

    四、spring 事务分类

    1、编程式事务管理

    Spring 提供的事务模版类:org.springframework.transaction.support.TransactionTemplate
    事务管理器:org.springframework.jdbc.datasource.DataSourceTransactionManager

    service impl 层的代码有所改动(注意,便于阅者copy实践,我就把整个类的代码贴出来,下同)

     1 package com.xpw.service.impl;
     2 
     3 import org.springframework.transaction.TransactionStatus;
     4 import org.springframework.transaction.support.TransactionCallback;
     5 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
     6 import org.springframework.transaction.support.TransactionTemplate;
     7 
     8 import com.xpw.dao.TradeDao;
     9 import com.xpw.service.TradeService;
    10 
    11 public class TradeServiceImpl implements TradeService {
    12 
    13     private TradeDao tradeDao;
    14     private TransactionTemplate transactionTemplate;
    15 
    16     public void setTradeDao(TradeDao tradeDao) {
    17         this.tradeDao = tradeDao;
    18     }
    19 
    20     public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    21         this.transactionTemplate = transactionTemplate;
    22     }
    23 
    24         //编程事务管理
    25     @Override
    26     public void trade(final int fromIdCard, final int toIdCard, final int money) {
    27         this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    28             
    29             @Override
    30             protected void doInTransactionWithoutResult(TransactionStatus arg0) {
    31                 tradeDao.outputMoney(fromIdCard, money);
    32                 tradeDao.inputMoney(toIdCard, money);
    33             }
    34         });
    35     }
    36 }
    View Code

    beans.xml

     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"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="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     
    10     <context:component-scan base-package="org.springframework.docs.test" />
    11     <context:property-placeholder location="jdbc.properties"/>    
    12     
    13     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    14         <property name="driverClassName" value="${jdbc.driverClassName}"/>
    15         <property name="url" value="${jdbc.url}"/>
    16         <property name="username" value="${jdbc.username}"/>
    17         <property name="password" value="${jdbc.password}"/>
    18     </bean>
    19     
    20     <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    21         <property name="transactionManager" ref="transactionManager"></property>
    22     </bean>
    23     <!-- 事务管理器 -->    
    24     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    25     </bean>
    26     
    27     <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    28         <constructor-arg ref="dataSource"></constructor-arg>
    29     </bean>
    30 
    31     <bean id="tradeDao" class="com.xpw.dao.impl.TradeDaoImpl">
    32         <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/>
    33     </bean>
    34 
    35     <bean id="tradeService" class="com.xpw.service.impl.TradeServiceImpl">
    36         <property name="tradeDao" ref="tradeDao"></property>
    37         <property name="transactionTemplate" ref="transactionTemplate"></property>
    38     </bean>
    39 </beans>
    View Code

    其它的代码都没有变

    结果:
    mysql> select * from trademoney;
    +--------+------+-------+
    | idCard | name | money |
    +--------+------+-------+
    |      1 | xx   |   300 |
    |      2 | ++   |   300 |
    +--------+------+-------+
    2 rows in set (0.00 sec)
    
    从上面的结果可以知道,编程式事务管理已经成功了,在 B + 50 失败了,回回滚,所以 A 不会 - 50

    2、声明式事务管理

    使用annotation

    service impl 层

     1 package com.xpw.service.impl;
     2 
     3 
     4 import org.springframework.transaction.annotation.Transactional;
     5 
     6 import org.springframework.transaction.support.TransactionTemplate;
     7 
     8 import com.xpw.dao.TradeDao;
     9 import com.xpw.service.TradeService;
    10 
    11 @Transactional
    12 public class TradeServiceImpl implements TradeService {
    13 
    14     private TradeDao tradeDao;
    15     private TransactionTemplate transactionTemplate;
    16 
    17     public void setTradeDao(TradeDao tradeDao) {
    18         this.tradeDao = tradeDao;
    19     }
    20 
    21     public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    22         this.transactionTemplate = transactionTemplate;
    23     }
    24 
    25     @Override
    26     public void trade(int fromIdCard, int toIdCard, int money) {
    27         this.tradeDao.outputMoney(fromIdCard, money);
    28         this.tradeDao.inputMoney(toIdCard, money);
    29     }
    30 
    31 }
    View Code

    beans.xml

     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"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop = "http://www.springframework.org/schema/aop" 
     6     xmlns:tx="http://www.springframework.org/schema/tx"
     7     xsi:schemaLocation="http://www.springframework.org/schema/beans
     8         http://www.springframework.org/schema/beans/spring-beans.xsd
     9         http://www.springframework.org/schema/context
    10         http://www.springframework.org/schema/context/spring-context.xsd
    11         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
    12         http://www.springframework.org/schema/aop
    13         http://www.springframework.org/schema/aop/spring-aop.xsd">    
    14     
    15     <context:component-scan base-package="org.springframework.docs.test" />
    16     <context:property-placeholder location="jdbc.properties"/>    
    17     
    18     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    19         <property name="driverClassName" value="${jdbc.driverClassName}"/>
    20         <property name="url" value="${jdbc.url}"/>
    21         <property name="username" value="${jdbc.username}"/>
    22         <property name="password" value="${jdbc.password}"/>
    23     </bean>
    24     
    25     <!-- 事务管理器 -->    
    26     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    27         <property name="dataSource" ref="dataSource"></property>
    28     </bean>
    29         
    30     <tx:annotation-driven transaction-manager="transactionManager"/>
    31     
    32     <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    33         <constructor-arg ref="dataSource"></constructor-arg>
    34     </bean>
    35 
    36     <bean id="tradeDao" class="com.xpw.dao.impl.TradeDaoImpl">
    37         <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/>
    38     </bean>
    39 
    40     <bean id="tradeService" class="com.xpw.service.impl.TradeServiceImpl">
    41         <property name="tradeDao" ref="tradeDao"></property>
    42     </bean>
    43 </beans>
    View Code
    结果:
    +--------+------+-------+
    | idCard | name | money |
    +--------+------+-------+
    |      1 | xx   |   300 |
    |      2 | ++   |   300 |
    +--------+------+-------+
    2 rows in set (0.00 sec)
    
    此方式成功 添加了事务管理

    使用xml 方式

    service impl 层

     1 package com.xpw.service.impl;
     2 
     3 import com.xpw.dao.TradeDao;
     4 import com.xpw.service.TradeService;
     5 
     6 public class TradeServiceImpl implements TradeService {
     7 
     8     private TradeDao tradeDao;
     9 
    10     public void setTradeDao(TradeDao tradeDao) {
    11         this.tradeDao = tradeDao;
    12     }
    13 
    14 
    15     @Override
    16     public void trade(int fromIdCard, int toIdCard, int money) {
    17         this.tradeDao.outputMoney(fromIdCard, money);
    18         this.tradeDao.inputMoney(toIdCard, money);
    19     }
    20 }
    View Code

    beans.xml

     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     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
     5     xsi:schemaLocation="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         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
    10         http://www.springframework.org/schema/aop
    11         http://www.springframework.org/schema/aop/spring-aop.xsd">
    12 
    13     <context:component-scan base-package="org.springframework.docs.test" />
    14     <context:property-placeholder location="jdbc.properties" />
    15 
    16     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    17         destroy-method="close">
    18         <property name="driverClassName" value="${jdbc.driverClassName}" />
    19         <property name="url" value="${jdbc.url}" />
    20         <property name="username" value="${jdbc.username}" />
    21         <property name="password" value="${jdbc.password}" />
    22     </bean>
    23 
    24     <!-- 事务管理器 -->
    25     <bean id="transactionManager"
    26         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    27         <property name="dataSource" ref="dataSource"></property>
    28     </bean>
    29 
    30     <!-- 事务通知器 -->
    31     <tx:advice>
    32         <tx:attributes>
    33             <tx:method name="*" />
    34         </tx:attributes>
    35     </tx:advice>
    36     <!-- 事务切面 -->
    37     <aop:config>
    38         <!-- 事务切点 -->
    39         <aop:pointcut expression="execution(* com.xpw.service.*.*(..))" id="transactionPointcut"/>
    40         <aop:advisor advice-ref="transactionPointcut"/>
    41     </aop:config>
    42 
    43     <bean id="namedParameterJdbcTemplate"
    44         class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    45         <constructor-arg ref="dataSource"></constructor-arg>
    46     </bean>
    47 
    48     <bean id="tradeDao" class="com.xpw.dao.impl.TradeDaoImpl">
    49         <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate" />
    50     </bean>
    51 
    52     <bean id="tradeService" class="com.xpw.service.impl.TradeServiceImpl">
    53         <property name="tradeDao" ref="tradeDao"></property>
    54     </bean>
    55 </beans>
    View Code
    结果
    
    mysql> select * from trademoney;
    +--------+------+-------+
    | idCard | name | money |
    +--------+------+-------+
    |      1 | xx   |   300 |
    |      2 | ++   |   300 |
    +--------+------+-------+
    2 rows in set (0.00 sec)   

    五、总结

    事务管理有编程式、声明式,本人推荐后者。因为前者,虽然实现了事务管理,但在一定程度上,非业务逻辑代码浸入了我们的业务逻辑代码,如果系统大型的话,也不可避免重复操作,代码看起来也不整洁了,也不方便后期维护。

    【tip】转载请注明原文来自 :http://www.cnblogs.com/chenmo-xpw/p/3949264.html

  • 相关阅读:
    数据更新
    MVC学习笔记
    const关键字同static readonly 的区别
    RSS
    C语言中取地址跟C++中的引用是一个意思吗?
    生产者消费者模式
    使用foreach的时候,不能对List进修改,怎么办?
    SQL查询
    Windows下的Java访问USB设备解决之道(翻译Java libusb / libusbwin32 wrapper)
    Java SE 6d新特性: 编译器 API
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/3949264.html
Copyright © 2011-2022 走看看