首页 > 代码库 > spring tranaction 事务入门
spring tranaction 事务入门
一、事务四个属性
二、事务的重要性
打个最简单的比方吧,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 }
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 }
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 }
Service层
1 package com.xpw.service;2 3 public interface TradeService {4 public void trade(int fromIdCard, int toIdCard, int money);5 }
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 }
(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>
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 }
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>
其它的代码都没有变
结果: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 }
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>
结果:+--------+------+-------+| 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 }
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>
结果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 事务入门