首页 > 代码库 > spring tranaction 事务入门

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     @Override20     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     @Override29     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     @Override15     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.Driverjdbc.url=jdbc:mysql://localhost:3306/springjdbc.username=rootjdbc.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     @Override26     public void trade(final int fromIdCard, final int toIdCard, final int money) {27         this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {28             29             @Override30             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 @Transactional12 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     @Override26     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/context10         http://www.springframework.org/schema/context/spring-context.xsd11         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 12         http://www.springframework.org/schema/aop13         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     @Override16     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/aop11         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

spring tranaction 事务入门