学习了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. Python+Requests接口测试教程(1):Fiddler抓包工具

    本书涵盖内容:fiddler.http协议.json.requests+unittest+报告.bs4.数据相关(mysql/oracle/logging)等内容.刚买须知:本书是针对零基础入门接口测 ...

  2. PhoneGap + Dreamweaver 5.5 无法在模拟器中打开的问题

    版权声明:本文为博主原创文章,未经博主允许不得转载. 原博客地址为:http://blog.csdn.net/dupang/article/details/8248335 按照网上的教程搭建Dream ...

  3. pomelo 安装 windows 下

    最近一直在捣鼓这个东西,看着个的先记录下发帖时间, pomelo 现在最新版是2.0 的,和之前的版本的启动时有区别的(命令行)的,可以进pomelo官网去看下基本的信息, 在pomelo官方论坛上的 ...

  4. Day4 - Linux分区规划与xshell使用排错

    1.1 没有重要数据 /boot   200M    存放系统的引导信息 内核 swap   交换分区   防止内存用光了 临时的一个内存 如果你的内存小于8G swap是内存的1.5倍   如果你的 ...

  5. HTML中document.getElementById()方法的操作

    转自:http://blog.csdn.net/pyffcwj/article/details/7240232/ obj = document.getElementById("cc" ...

  6. Tomcat session生成算法

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt396 修改TOMCAT 默认的生成SESSION ID的算法和字符长度非常简 ...

  7. 电商Banner设计背后的12个人性的秘密

  8. 转:swagger 入门

    前言 swagger ui是一个API在线文档生成和测试的利器,目前发现最好用的. 为什么好用?Demo 传送门 支持API自动生成同步的在线文档 这些文档可用于项目内部API审核 方便测试人员了解A ...

  9. 团队作业8——第二次项目冲刺(Beta阶段)5.21

    1.当天站立式会议照片 会议内容: 本次会议为第三次会议 本次会议在陆大楼2楼召开,本次会议内容: ①:检查总结第二次任务完成情况 ②:布置第三次任务的详细分工 ③:规定完成时间是在第四次任务之前 ④ ...

  10. JAVA基础第二组(5道题)

    6.[程序6] 题目:输入两个正整数m和n,求其最大公约数和最小公倍数.        1.程序分析:利用辗除法. package com.niit.homework1; import java.ut ...