Spring框架学习(10)Spring中如何使用事务?
内容源自:Spring中如何使用事务?
一、为什么要使用事务?
如果我们一个业务逻辑只执行一次sql,是不需要使用事务的。但如果要执行多条sql语句才能完成一个业务逻辑的话,这个时候就要使用事务了。 因为这几条sql可能有的执行成功,有的执行失败。 而事务就是对一组sql语句进行统一的提交或回滚操作,为了保证数据执行的一致性,这组sql不是全部成功就是全部失败。
举个例子吧:
我们要实现转账的功能。首先要在账户a中扣100元,然后在账户b中加100元,这里涉及两次sql操作。大概像下面代码这样操作:
boolean flag1 = accountDao.minus(map)==1;
if(flag1){
// 减成功
map.put("toAccount", toAccount);
boolean flag2 = accountDao.plus(map)==1;
if(flag2){
// 加成功
return true;
}else{
/** 加失败 [减生效了] 回滚
* 为这个转账的过程添加事务控制
// 自定义异常
throw new PayException();
}
}else{
// 减失败
return false;
}
如果账户a减钱成功,账户b加钱失败(比如账户输入错误,数据库中没有这个账户,sql执行失败), 这里显然要把a账户减的钱还回来。即回滚。所以在这里需要添加事务控制。
二.如何在spring中添加事务
- spring中的事务 作为 局部事务 , 配置方式依赖于持久层使用的技术
spring整合jdbc
spring整合hibernate
- spring中即提供了编程式事务的管理方式,也提供了声明式事务的管理方式:
【编程式事务 TransactionTemplate
模板类 将事务的管理过程封装模板类中】
【声明式事务 AOP
提供根接口 PlatFormTransactionManager 事务管理器接口
用于描述spring中事务如何管理[如何创建、如何提交、如何回滚] 】
- 声明式事务
底层采用AOP技术实现,将事务管理过程(创建、提交、回滚)封装在一个事务通知bean[AfterAdvice ThrowsAdvice]中;
通过在ioc容器中配置切入点的方式,将这个事务通知bean提供的事务管理功能引用给需要事务的核心业务逻辑方法(DAO)
在容器中添加配置如下:(这里orm用的mybatis)
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:component-scan base-package="com"/>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/etoak"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="ds"></property>
<property name="mapperLocations">
<list>
<value>classpath:com/etoak/dao/AccountDaoIf-mapper.xml</value>
</list>
</property>
</bean>
<bean id="accountDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="ssf"></property>
<property name="mapperInterface" value="com.etoak.dao.AccountDaoIf"></property>
</bean>
<!--
配置声明式事务!
1 aop命名空间、schema文件
tx命名空间、schame文件(用于提供声明式事务的支持)
2 配置事务通知bean [Advice]
[before after around throws]
管理事务的使用方式[创建、提交、回滚]
transaction-manager: 设置事务管理器
事务管理器 PlatFormTransactionManager
- DataSourceTransactionManager
-->
<tx:advice id="tran" transaction-manager="tm">
<tx:attributes>
<!--
tx:method 为不同类型的方法添加不同的事务属性
-->
<tx:method name="pay"
isolation="DEFAULT"
propagation="REQUIRED"
read-only="false"
timeout="-1"
rollback-for="com.etoak.util.PayException"/>
<tx:method name="add*"/>
<tx:method name="del*"/>
<tx:method name="sel*" read-only="true"/>
<tx:method name="update*" timeout="10"/>
</tx:attributes>
</tx:advice>
<!--
配置事务管理器bean
-->
<bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!--
3 配置切入点
描述需要将通知[tran]提供的功能[事务管理功能]引用给哪个/哪些方法
-->
<aop:config>
<aop:pointcut
expression="execution(* com.etoak.service.*.*(..))"
id="pc"/>
<aop:advisor advice-ref="tran" pointcut-ref="pc"/>
</aop:config>
</beans>
配置好了,还要写一个异常类,在需要事务管理的地方抛出自己定义的异常,从而启用事务。
public class PayException extends Exception{
@Override
public String getMessage() {
return "减操作成功,加操作失败,失败原因:没有这个账户.转账失败,我要回滚";
}
}
在web.xml中添加异常页面配置:
<error-page>
<exception-type>com.etoak.util.PayException</exception-type>
<location>/error.jsp</location>
</error-page>
方法里面添加事务管理:
public class PayService {
@Autowired
private AccountDaoIf accountDao;
// 提供转账服务
public boolean pay(String fromAccount , String toAccount , Double money)throws Exception{
// 调用DAO
double yue = accountDao.查询余额(fromAccount);
if(yue>=money){
Map map = new HashMap();
map.put("fromAccount", fromAccount);
map.put("money" , money);
boolean flag1 = accountDao.minus(map)==1;
if(flag1){
// 减成功
map.put("toAccount", toAccount);
boolean flag2 = accountDao.plus(map)==1;
if(flag2){
// 加成功
return true;
}else{
/** 加失败 [减生效了] 回滚
* 为这个转账的过程添加事务控制
* 添加声明式事务
* 以AOP的方式进行添加
* 将事务的管理过程封装在一个事务通知bean
* 以配置、引用的方式将事务通知bean添加给需要事务的方法
* 切入点指向的是哪 : 服务层中Service对象提供的pay()
*
* 声明式事务回滚的方式:检测到异常时
*/
// 自定义异常
throw new PayException();
}
}else{
// 减失败
return false;
}
}else{
return false;
}
}
}
Spring框架学习(10)Spring中如何使用事务?的更多相关文章
- Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建
上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...
- Spring框架学习02——Spring IOC 详解
1.Spring IOC的基本概念 IOC(Inverse of Control)反转控制的概念,就是将原本在程序中手动创建对象的控制权,交由Spring框架管理.当某个Java对象(调用者)需要调用 ...
- Spring框架学习03——Spring Bean 的详解
1.Bean 的配置 Spring可以看做一个大型工厂,用于生产和管理Spring容器中的Bean,Spring框架支持XML和Properties两种格式的配置文件,在实际开发中常用XML格式的配置 ...
- Spring 框架学习(1)--Spring、Spring MVC扫盲
纸上得来终觉浅,绝知此事要躬行 文章大纲 什么是spring 传统Java web应用架构 更强的Java Web应用架构--MVC框架 Spring--粘合式框架 spring的内涵 spring核 ...
- Spring框架学习10——JDBC Template 实现数据库操作
为了简化持久化操作,Spring在JDBC API之上提供了JDBC Template组件. 1.添加依赖 添加Spring核心依赖,MySQL驱动 <!--Spring核心基础依赖--> ...
- Spring框架学习1
AnonymouL 兴之所至,心之所安;尽其在我,顺其自然 新随笔 管理 Spring框架学习(一) 阅读目录 一. spring概述 核心容器: Spring 上下文: Spring AOP ...
- Spring框架学习之IOC(二)
Spring框架学习之IOC(二) 接着上一篇的内容,下面开始IOC基于注解装配相关的内容 在 classpath 中扫描组件 <context:component-scan> 特定组件包 ...
- Spring框架学习笔记(5)——Spring Boot创建与使用
Spring Boot可以更为方便地搭建一个Web系统,之后服务器上部署也较为方便 创建Spring boot项目 1. 使用IDEA创建项目 2. 修改groupid和artifact 3. 一路n ...
- Spring框架学习一
Spring框架学习,转自http://blog.csdn.net/lishuangzhe7047/article/details/20740209 Spring框架学习(一) 1.什么是Spring ...
- spring框架学习(三)junit单元测试
spring框架学习(三)junit单元测试 单元测试不是头一次听说了,但只是听说从来没有用过.一个模块怎么测试呢,是不是得专门为一单元写一个测试程序,然后将测试单元代码拿过来测试? 我是这么想的.学 ...
随机推荐
- Java学习笔记(十)——xml
[前面的话] 学习过程中还是效率不够高,老是容易注意力不集中,着急啊.不能在这样了,要好好学习,好好努力. 学习过程中的小知识点总结,基础知识,选择阅读. [xml定义] 定义:可扩展标记语言(英语: ...
- Java学习笔记(一)——关于java中的String类
[前面的话] 毕业将近6个月了,试用期也快要过去了,期待接下来的日子.在金融类性质的机构,最痛苦的是也许就是大部分系统外包,所以比较少写代码,在这六个月中只写了1个月左右的代码,然后每天都在做一些比较 ...
- gdbserver静态编译
redhat9 编译gdb server(静态编译)下载gdb-6.2a.tar:http://download.chinaunix.net/download.php?id=6680&Reso ...
- NIO使用Reactor模式遇到的问题
关于Reactor模式,不再多做介绍,推荐Doug Lea大神的教程:Java 可扩展的IO 本来在Reactor的构造方法中完成一系列操作是没有问题的: public class Reactor i ...
- CodeForces 809D Hitchhiking in the Baltic States(FHQ-Treap)
题意 给你长度为$n$的序列,序列中的每个元素$i$有一个区间限制$[l_i,r_i]$,你从中选出一个子序列,并给它们标号$x_i$,要求满足 $,∀i<j,x_i<x_j$,且$, ∀ ...
- SQL中on和where的使用及其差异
在编写SQL脚本中,多表连接查询操作需要使用到on和where条件,但是经常会混淆两者的用法,从而造成取数错误.为此,使用测试数据进行总结如下: 1.现有两张测试表,table_a和table_b. ...
- cogs 2039. 树的统计
2039. 树的统计 ★★ 输入文件:counttree.in 输出文件:counttree.out 简单对比时间限制:1 s 内存限制:128 MB [题目描述] 关于树的统计问题有 ...
- qsc round#2 喵哈哈村的排队(本辣鸡想七想八的,特写此博文给自己一个提醒)
该oj是qsc自己写的比赛,友情链接:http://qscoj.cn/ 喵哈哈村的排队 发布时间: 2017年2月26日 16:13 最后更新: 2017年2月26日 16:14 时间限制: ...
- Gym 101128F Sheldon Numbers(网络流)
[题目链接] http://codeforces.com/gym/101128/attachments [题目大意] 给出一张地图,分为高地和低地,高低地的交界线上划有红线, 现在要开小车跨过每条红线 ...
- 数据库之mysql的基本操作
1 数据库 1.1 数据库介绍 为什么要有数据库? 数据需要大量的存储,把数据永久保存下来,可以保存到文件中,当然也可以保存到数据库中. 数据库:通俗的说,存储数据的仓库,是管理数据的文件夹:存放数据 ...