spring 学习(五):spring 事务
spring 学习(五):spring 事务
事务概要
一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的:
- 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
- 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
所以事务是用来处理异常和并发问题的。
spring 事务管理
spring 的事务管理我们一般采用声明式事务管理这种方式,有两种方式实现:
- 基于 xml 配置文件实现
- 基于注解实现
一般使用 PlatformTransactionManager这个事务接口来实现 spring 事务管理。
spring 针对不同的 dao 层框架,提供了接口不同的实现类。
由于现在一般使用 spring JDBC 和 iBatis ,所以我们使用
org.springframework.jdbc.datasource.DataSourceTransactionManager
这个类来实现数据的持久化操作。
spring 实例
我们还是举个栗子来进行 spring 事务操作,以转账操作为例:一人少钱,一人多钱。
1 创建数据库表 account,添加数据,如下图所示:

2 创建 OrdersDao.java 和 OrdersService.java ,实现数据操作:
OrdersDao.java:
package cn.itcast.dao;
import org.springframework.jdbc.core.JdbcTemplate;
public class OrdersDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/*
做对数据库操作的方法,不写业务操作
*/
//少钱的方法
public void lessMoney(){
String sql = "update account set salary=salary+? where username=?";
jdbcTemplate.update(sql, -1000, "小王");
}
//多钱的方法
public void moreMoney(){
String sql = "update account set salary=salary+? where username=?";
jdbcTemplate.update(sql, 1000, "小马");
}
}
OrdersService:
package cn.itcast.service;
import cn.itcast.dao.OrdersDao;
import org.springframework.transaction.annotation.Transactional;
// @Transactional 使用注解时的操作
public class OrdersService {
private OrdersDao ordersDao;
public void setOrdersDao(OrdersDao ordersDao) {
this.ordersDao = ordersDao;
}
/*
业务逻辑层,写转账业务
调用 dao 方法
*/
public void accountMoney(){
//小王少1000
ordersDao.lessMoney();
int i = 10/0; //抛出异常操作
//小马多1000
ordersDao.moreMoney();
}
}
- service 层又叫业务逻辑层
- dao 层,单纯对数据库操作层,在 dao 层不添加业务
我们在编写程序的时候最好按照这种规范操作。
3 创建 applicationContext.xml 文件,完成注入关系,并添加事务模块,出现异常进行回滚操作,配置文件使用 aop 思想配置:
<?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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 注入属性值 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///sampledb"></property>
<property name="user" value="root"></property>
<property name="password" value=""></property>
</bean>
<!-- 第一步 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入 dataSource -->
<property name="dataSource" ref="dataSource"> </property>
</bean>
<!-- 第二步 配置事务增强 -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!-- 做事务操作 -->
<tx:attributes>
<tx:method name="account*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 第三步 配置切面 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut id="pointcut1" expression="execution(* cn.itcast.service.OrdersService.*(..))"/>
<!-- 切面 -->
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
</aop:config>
<bean id="ordersService" class="cn.itcast.service.OrdersService">
<property name="ordersDao" ref="ordersDao"></property>
</bean>
<bean id="ordersDao" class="cn.itcast.dao.OrdersDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
当然我们还可以采用注解的方式进行事务管理,只需修改配置文件:
<?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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 注入属性值 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///sampledb"></property>
<property name="user" value="root"></property>
<property name="password" value=""></property>
</bean>
<!-- 第一步 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 第二步 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="ordersService" class="cn.itcast.service.OrdersService">
<property name="ordersDao" ref="ordersDao"></property>
</bean>
<bean id="ordersDao" class="cn.itcast.dao.OrdersDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
然后在要使用事务的方法所在类上面添加注解 @tTransactional 。
4 我们编写一个测试类来查看当抛出异常时数据库能不能进行回滚操作。
创建 TestService.java:
package cn.itcast.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestService {
@Test
public void testDemo(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
OrdersService ordersService = (OrdersService) context.getBean("ordersService");
ordersService.accountMoney();
}
}
运行测试文件,可以看到在控制台抛出异常:

是因为我们在 OrdersService.java 的 accountMoney() 方法下加入了下面这行:
int i = 10/0;
这是不允许的。查看我们数据库中的数据,可以看到内容没有变,所以是进行了回滚操作的,不然按业务逻辑会出现一方少1000,而另一方内容不变。

spring 学习(五):spring 事务的更多相关文章
- Spring学习(十一)-----Spring使用@Required注解依赖检查
Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...
- Spring学习(六)-----Spring使用@Autowired注解自动装配
Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...
- Spring学习(十九)----- Spring的五种事务配置详解
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...
- spring深入学习(五)-----spring dao、事务管理
访问数据库基本是所有java web项目必备的,不论是oracle.mysql,或者是nosql,肯定需要和数据库打交道.一开始学java的时候,肯定是以jdbc为基础,如下: private sta ...
- spring学习(三) ———— spring事务操作
前面一篇博文讲解了什么是AOP.学会了写AOP的实现,但是并没有实际运用起来,这一篇博文就算是对AOP技术应用的进阶把,重点是事务的处理. --wh 一.jdbcTemplate 什么是JdbcTem ...
- spring学习 8-面试(事务,解决线程安全)
1.介绍一下Spring的事物管理 参考:Spring 学习7 -事务 2.Spring如何处理线程并发问题 Spring使用ThreadLocal解决线程安全问题 参考:Spring学习11- ...
- Spring学习之Spring中AOP方式切入声明式事务
mybatis-spring官方文档说明 一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中.而不是给 MyBatis 创建一个新的 ...
- Spring学习五----------Bean的配置之Bean的生命周期
© 版权声明:本文为博主原创文章,转载请注明出处 Bean的生命周期 1.定义 2.初始化 3.使用 4.销毁 初始化和销毁的三种方式 1.实现org.springframework.beans.fa ...
- Spring学习笔记--spring+mybatis集成
前言: 技术的发展, 真的是日新月异. 作为javaer, 都不约而同地抛弃裸写jdbc代码, 而用各种持久化框架. 从hibernate, Spring的JDBCTemplate, 到ibatis, ...
- spring boot(五)Spring data jpa介绍
在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...
随机推荐
- VS2017自动添加头部注释
让VS自动生成类的头部注释,只需修改两个文集即可,一下两个路径下个有一个 Class.cs文件 D:\Program Files (x86)\Microsoft Visual Studio\2017\ ...
- PHP开发环境正确的错误信息处理
正确记录配置 php.ini display_errors = On error_reporting = E_ALL log_errors = On error_log = F:/data/php/e ...
- cs231n线性分类器作业 svm代码 softmax
CS231n之线性分类器 斯坦福CS231n项目实战(二):线性支持向量机SVM CS231n 2016 通关 第三章-SVM与Softmax cs231n:assignment1——Q3: Impl ...
- krpano之背景音乐
步骤: 1.添加音乐控制插件 <!-- START:音乐控制 --> <plugin name="soundinterface" url="%SWFPA ...
- 搜索——深度优先搜索(DFS)
设想我们现在身处一个巨大的迷宫中,我们只能自己想办法走出去,下面是一种看上去很盲目但实际上会很有效的方法. 以当前所在位置为起点,沿着一条路向前走,当碰到岔道口时,选择其中一个岔路前进.如果选择的这个 ...
- 斯坦福CS229机器学习课程笔记 part3:广义线性模型 Greneralized Linear Models (GLMs)
指数分布族 The exponential family 因为广义线性模型是围绕指数分布族的.大多数常用分布都属于指数分布族,服从指数分布族的条件是概率分布可以写成如下形式:η 被称作自然参数(nat ...
- 爬虫模块之Request
requests Requests唯一一个非转基因的Python HTTP库,人类就可以安全享用. Python标准库中提供了:urllib.urllib2.httplib等模块以供Http请求,但是 ...
- Python基本数据类型--列表、元组、字典、集合
一.Python基本数据类型--列表(List) 1.定义:[ ]内以逗号分隔,按照索引,存放各种数据类型,每个位置代表一个元素. 2.列表的创建: # 方式一 list1 = ['name','ag ...
- instanceof php
instdnceof php5 的一个新成员 功能: 使用这个关键字可以确定一个对象是否是类的实例,是否是累的子类 ,还是实现了某个特定的接口. <?php class A{} class B ...
- c++ 装饰模式(decorate)
装饰模式:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类 更为灵活.有时我们希望给某个对象而不是整个类添加一些功能.比如有一个手机,允许你为手机添加特性,比如增加挂件.屏幕贴 ...