我的Spring学习记录(三)
学习了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学习记录(三)的更多相关文章
- Spring学习记录(三)---bean自动装配autowire
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系,少写几个ref autowire: no ---默认情况,不自动装配,通过ref手动引用 byName---根据 ...
- Spring学习记录(三)
一.AOP的整理总结 aop面向切面编程 横向重复代码,纵向抽取 动态代理 1.通过动态代理可以体现aop思想 2.为什么要哦用动态代理:对目标对象中的方法进行增强 spring aop开发 spri ...
- 我的Spring学习记录(五)
在我的Spring学习记录(四)中使用了注解的方式对前面三篇做了总结.而这次,使用了用户登录及注册来对于本人前面四篇做一个应用案例,希望通过这个来对于我们的Spring的使用有一定的了解. 1. 程序 ...
- Spring 学习记录8 初识XmlWebApplicationContext(2)
主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...
- MyEclipse Spring 学习总结三 SpringMVC
MyEclipse Spring 学习总结三 SpringMVC 一.SpringMVC原理 1.Springmvc 框架介绍 1)Spring 框架停工了构建Web应用程序的全功能MVC模块.Spr ...
- 我的Spring学习记录(二)
本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...
- 我的Spring学习记录(四)
虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼. ...
- Spring 学习记录3 ConversionService
ConversionService与Environment的关系 通过之前的学习(Spring 学习记录2 Environment),我已经Environment主要是负责解析properties和p ...
- Spring 学习记录6 BeanFactory(2)
主题 除了Spring 学习记录5 BeanFactory 里写的几个接口外,BeanFactory的实现类还实现了一些其他接口,这篇文章主要介绍这些接口和实现类. 结构 DefaultListabl ...
- spring 学习(三):aop 学习
spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...
随机推荐
- Jsp/html页面删除前进行删除提示
HTML代码 <body> <a href="javascript:if(window.confirm('是否?')){window.location.href='test ...
- HTML (Hyper Text Markup Language) 常用标签
HTML是什么? 英文全称:Hyper Text Markup Language 中文全称:超文本标记语言 网页主要由 机构 表现 行为 组成 什么是标签? < > 里的叫 ...
- Ext:ComboBox实战
var gsCombo = new Ext.form.ComboBox({ id:'combo', hiddenName:'value', fieldLabel:'下拉框', triggerActio ...
- java 利用jna调用c#的dll
一.需求阐述: 如果我们的项目利用c#开发,到了开发后期需要和java组进行合作,其中有一部分业务逻辑利用c#已经code completed,那么我们可能会考虑用java来调用现成的c#dll实现需 ...
- 服务端性能测试 TPS
针对服务器端的性能,以TPS为主来衡量系统的性能,并发用户数为辅来衡量系统的性能,如果必须要用并发用户数来衡量的话,需要一个前提,那就是交易在多长时间内完成,因为在系统负载不高的情况下,将思考时间( ...
- salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现
项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...
- 实战案例--TEMPDB暴涨
前言 tempdb暴增,造成磁盘空间不足,甚至影响业务运行. 正文 如图,tempdb log文件从7.40开始突然暴涨,因为 tempdb 0 M到 40G tempdb 所 ...
- oracle查看锁和释放锁
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt108 Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程 ...
- JVM中锁优化,偏向锁、自旋锁、锁消除、锁膨胀
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt364 本文将简单介绍HotSpot虚拟机中用到的锁优化技术. 自旋锁 互斥同 ...
- CSS display和visibility的用法和区别
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt408 大多数人很容易将CSS属性display和visibility混淆,它 ...