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 }

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     @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 }

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     @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 }

(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.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 }

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 @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 }

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>

结果:
+--------+------+-------+
| 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 }

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>

结果

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

时间: 2024-11-09 03:44:10

spring tranaction 事务入门的相关文章

Spring 事务入门

定义: 一系列的动作,被当成一个单独的工作单元,要么都完成,要么全部不起作用. 之前的事务处理:JDBC与Hibernate中的事务处理--与try...catch...finally...一起用.Spring中的事务处理:编程式,声明式.Spring从事务管理的API中抽象出一套独立事务机制.事务管理代码能独立于特点的具体技术. 使用方法: 建立beans.xml 准备工作:配置数据源对象. <!-- 生成数据连接池 --> <bean class="com.mchange.

Spring的快速入门第一天

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.06.21 lutianfei none 本文内容 Spring框架的概述 Spring的快速入门 Spring 工厂接口 在MyEclipse 配置Spring的xml文件提示 IoC容器装配Bean(xml配置方式) Ioc容器装配Bean(注解方式) 在web项目中集成Spring Spring 整合 junit4 测试 Spring框架学习路线 Spring的Ioc Spring的AOP , AspectJ S

spring的事务

Chapter 1. Spring中的事务控制(Transacion Management with Spring) Table of Contents 1.1. 有关事务(Transaction)的楔子 1.1.1. 认识事务本身 1.1.2. 初识事务家族成员 1.2. 群雄逐鹿下的Java事务管理 1.2.1. Java平台的局部事务支持 1.2.2. Java平台的分布式事务支持 1.2.2.1. 基于JTA的分布式事务管理 1.2.2.1.1. JTA编程事务管理 1.2.2.1.2.

Spring Boot事务管理(下)

在上两篇 Spring Boot事务管理(上)和Spring Boot事务管理(中)的基础上介绍注解@Transactional. 5 @Transactional属性 属性 类型 描述 value String 指定使用的事务管理器 propagation enum: Propagation 可选的事务传播行为设置 isolation enum: Isolation 可选的事务隔离级别设置 readOnly boolean 读写或只读事务,默认读写 timeout int,unit secon

Spring的事务机制

JAVA EE传统事务机制 通常有两种事务策略:全局事务和局部事务.全局事务可以跨多个事务性资源(即数据源,典型的是数据库和消息队列),通常都需要J2EE应用服务器的管理,其底层需要服务器的JTA支持.而局部事务则与底层采用的持久化技术有关,如果底层直接使用JDBC,需要用Connection对象来操事务.如果采用Hibernate持久化技术,则需要使用session对象来操作事务. 通常的,使用JTA事务,JDBC事务及Hibernate事务的编程流程大致如下, 上图也可以看出,采用传统事务编

Spring分布式事务

[如何实现XA式.非XA式Spring分布式事务] [http://www.importnew.com/15812.html] 在JavaWorld大会上,来自SpringSource的David Syer跟大家分享了Spring应用的几种事务处理机制.读完此文,你可以了解可以用分布式事务做些什么.不能做什么以及如何.何时避免使用XA,何时必须使用.

spring与事务管理

就我接触到的事务,使用最多的事务管理器是JDBC事务管理器.现在就记录下在spring中是如何使用JDBC事务管理器 1)在spring中配置事务管理器 <!-- JDBC事务 -->    <bean id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property

Spring初学之spring的事务管理xml

所有的java类都是用的上一篇文章:Spring初学之spring的事务管理 不同的是,这时xml配置事务,所以就要把java类中的那些关于spring的注解都删掉,然后在xml中配置,ApplicationContext.xml如下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans&q

8 -- 深入使用Spring -- 6... Spring的事务

8.6 Spring 的事务 8.6.1 Spring支持的事务策略 8.6.2 使用XML Schema配置事务策略 8.6.3 使用@Transactional 啦啦啦 我早就肯定我的身体 被罪恶领入死亡里 可从来没有想过 现在还能这样 散发出芬香气息...