学习了AOP之后就可以应用一下了,所以这次我们了解一下Spring的声明式事务。

事务在我们的很多方面都可以体现,就拿我们平时的买卖活动,或者是银行的转账来说,这些活动要么是成功,要么是失败,比如:张三给李四转账100块钱,我们的实现是张三的账户划掉100然后李四的账户加上100,这是一个整体,要么成功,要么失败。我们不可能说张三的账户少了钱,但是因为某种原因导致李四的账户没多钱。所以说我们要通过某种机制保证这个整体活动的成功。接下来进入主题。

  

1. Spring事务简介

1.1 事务的四要素

名称 内容
原子性(atomicity) 整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。
一致性(consistency) 一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
隔离性(isolation) 隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。
持久性(durability) 在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

1.2 Spring事务管理方式

  • 编程式事务

    编程式事务从名字应该可以看出,就是事务的管理方式由自己编写代码来实现,主要的实现方式就是通过对事务的代码嵌入进去我们的业务代码之中
  • 声明式事务

    声明事务主要是利用了Spring AOP通过面向切面编程把事务代码直接嵌入事务代码中,所以这里我们获取到的有事务管理的Bean实际上是Spring经过加工之后的代理类

概念性的东西不是内行,关于Spring事务的一些概念性的东西可以参考一下链接,希望有帮助

事务简介

|-https://baike.baidu.com/item/acid/10738?fr=aladdin

Spring事务

|-http://www.cnblogs.com/ysxlin/archive/2008/06/06/1215300.html

|- http://lxy2330.iteye.com/blog/1122183

|- http://www.cnblogs.com/longshiyVip/p/5061637.html

2. Spring事务准备工作

现在有两个人需要进行转账工作,我这里就随便的设计了这么一个剧情了,首先有一个dao(Data Access Object数据访问对象,与数据库打交道,这里我没有使用接口来实现,但是在一般的应用中是需要用接口实现的)

//这里继承了JdbcTemplate主要是方便实现,它对我们的Jdbc进行了封装,可以使我们不用考虑数据库连接关闭等等的问题
//而且此次的Spring事务主要是说的Jdbc事务
public class TransferDao extends JdbcTemplate { /**
* 将钱的数目转向当前user的账户
* @param money money
* @param username username
*/
public void transferMoneyToOne(Float money, String username){
this.update("UPDATE account SET money = money + (?) WHERE username = ?", money, username);
}
}

还有一个service(这里主要是写我们业务相关的代码)

public class TransferService {

    private TransferDao dao;

	/**
* 转账业务,这里为了方便直接写了张三转给了李四100块钱
*/
public void transferMoney(){
dao.transferMoneyToOne((float) -100, "张三");
// int i = 1 / 0;//为了测试出现异常的情况,测试时可去掉
dao.transferMoneyToOne((float) 100, "李四");
// throw new RuntimeException("这里突然死机了");//测试时可去掉
} public TransferDao getDao() {
return dao;
} public void setDao(TransferDao dao) {
this.dao = dao;
}
}

上面注释抛出的异常和代码错误主要是为了等下代码测试的时候模拟我们日常中可能出现的各种错误

这里还需要一个数据库和表(数据库自建,表的sql在下方)

-- ----------------------------
-- Table structure for man
-- ----------------------------
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`username` varchar(255) default NULL,
`money` float(255,0) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of man
-- ----------------------------
INSERT INTO `account` VALUES ('张三', '9600');
INSERT INTO `account` VALUES ('李四', '970');

3. Spring事务配置

事务需要加入的依赖较之前的需要加入tx依赖而且涉及数据库操作需要mysql连接包以及数据库连接池,这里使用的是阿里的druid,maven的pom.xml依赖主要如下:

 <properties>
<spring.version>4.3.10.RELEASE</spring.version>
</properties> <dependencies>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>

以下是classpath下的applicationContext.xml配置文件

因为是事务配置与之前的相比需要加入tx命名约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!--配置DataSource-->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--以下是数据库连接的具体信息-->
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_demo_1"/>
</bean> <!--配置TransferDao-->
<bean class="cn.lger.dao.TransferDao" name="transferDao">
<property name="dataSource" ref="dataSource"/>
</bean> <!--配置TransferService-->
<bean name="transferService" class="cn.lger.service.TransferService">
<property name="dao" ref="transferDao"/>
</bean> <!--配置管理事务的类-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <!--给定管理事务的类 设置通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
这里设置需要事务操作的方法(切入点),
其中还有一些属性没有写,这里全部采用默认操作,
*为全部都需要事务操作
-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice> <!--配置切面-->
<aop:config>
<!--设置切入点-->
<aop:pointcut id="txPointcut" expression="execution(* cn.lger.service.TransferService.*(..))"/>
<!--给定之前配置的通知-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config> </beans>

在上面的tx通知配置中<tx:method name="*"/>,注释写明了采用默认的操作,但是这里还是提一下,<tx:method name="被代理方法名(需要事务管理的方法)" propagation="传播行为" read-only="是否只读" isolation="隔离级别" timeout="事务所需最大时间"/> 这里不作赘述,下面的链接我个人觉得解释的很好

事务配置之<tx:method/> 有关的设置

http://blog.sina.com.cn/s/blog_4a40057401000865.html

http://www.iteye.com/topic/410461

4. Spring事务测试

经过以上的准备工作以及配置这个项目已经能够运行了,所以,我们现在来测试一下当没有发生异常的情况下是否能够转账成功

public class TestTx {

    /**
* 测试service的转账功能
*/
@Test
public void test01(){
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
TransferService service = context.getBean(TransferService.class);
service.transferMoney();
}
}

经过测试张三成功地转账给了李四100元,然后我们把之前的TransferService的异常的注释给去掉,然后进行测试,发现数据库中的数据稳如泰山,不会变,这就是事务,当抛出异常时会影响事务的ACID四要素,这个整体活动当然不会成功执行,所以,你看到的这就是事务。

上面代码可以在Github下载

我的Spring学习记录(三)的更多相关文章

  1. Spring学习记录(三)---bean自动装配autowire

    Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系,少写几个ref autowire: no ---默认情况,不自动装配,通过ref手动引用 byName---根据 ...

  2. Spring学习记录(三)

    一.AOP的整理总结 aop面向切面编程 横向重复代码,纵向抽取 动态代理 1.通过动态代理可以体现aop思想 2.为什么要哦用动态代理:对目标对象中的方法进行增强 spring aop开发 spri ...

  3. 我的Spring学习记录(五)

    在我的Spring学习记录(四)中使用了注解的方式对前面三篇做了总结.而这次,使用了用户登录及注册来对于本人前面四篇做一个应用案例,希望通过这个来对于我们的Spring的使用有一定的了解. 1. 程序 ...

  4. Spring 学习记录8 初识XmlWebApplicationContext(2)

    主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...

  5. MyEclipse Spring 学习总结三 SpringMVC

    MyEclipse Spring 学习总结三 SpringMVC 一.SpringMVC原理 1.Springmvc 框架介绍 1)Spring 框架停工了构建Web应用程序的全功能MVC模块.Spr ...

  6. 我的Spring学习记录(二)

    本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...

  7. 我的Spring学习记录(四)

    虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼. ...

  8. Spring 学习记录3 ConversionService

    ConversionService与Environment的关系 通过之前的学习(Spring 学习记录2 Environment),我已经Environment主要是负责解析properties和p ...

  9. Spring 学习记录6 BeanFactory(2)

    主题 除了Spring 学习记录5 BeanFactory 里写的几个接口外,BeanFactory的实现类还实现了一些其他接口,这篇文章主要介绍这些接口和实现类. 结构 DefaultListabl ...

  10. spring 学习(三):aop 学习

    spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...

随机推荐

  1. webpack教程(六)——分离组件代码

    先来运行一下webpack命令, 看到app.js才4k. 安装一下react npm install react --sava-dev 在app/index.js文件内引入react 运行webpa ...

  2. 页面性能优化和高频dom操作

    一.DOM操作影响页面性能的核心问题 通过js操作DOM的代价很高,影响页面性能的主要问题有如下几点: 访问和修改DOM元素 修改DOM元素的样式,导致重绘或重排 通过对DOM元素的事件处理,完成与用 ...

  3. B树及B+树

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp80 B树及B+树 一.B树 1.B树的定义    B树是一种平衡的多分树 ...

  4. android-学习1 配置环境

    转载注明出处,谢谢--http://www.cnblogs.com/JK-HYJ/ 前提:电脑先配置好java的环境-- adk_bundle下载安装地址:http://tools.android-s ...

  5. 开始学习.net的第二天

    今天由于原因上午没上课.下午去了学的.net的表格. <body></body><img src="../temp/新建文件夹/64aab4ae3e632dbc ...

  6. CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用

    作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...

  7. poj 1742 多重背包

    题意:给出n种面值的硬币, 和这些硬币每一种的数量, 要求求出能组成的钱数(小于等于m) 思路:一开始直接用多重背包套上去超时了,然后就没辙了,然后参考网上的,说只需要判断是否能取到就行了,并不需要记 ...

  8. C# 文件的上传和下载

    本文主要介绍一下,在APS.NET中文件的简单上传于下载,上传是将文件上传到服务器的指定目录下,下载是从存入数据库中的路径,从服务器上下载. 1.上传文件 (1)页面代码 <table alig ...

  9. [转载]dreamweaver代码提示失效

    原文地址:dreamweaver代码提示失效作者:云中雁 2007-03-23 12:19:22|  分类: 编程手记 |  标签:web2.0  javascript   |字号大中小 订阅 吴庆民 ...

  10. px,em,rem的关系

    之前听人说过,网站制作中字体单位应该用em而不用px,为什么呢?原因简单来说就是em支持IE6下的字体缩放,在页面中按ctrl+滚轮,字体以px为单位的网站没有反应.px是绝对单位,不支持IE的缩放, ...