SSM(spring mvc+spring+mybatis)学习路径——1-2、spring事务管理
目录
内容可能存在MK版本兼容原因显示异常,可以异步我的github上的readme观看。该篇源码和readme地址:https://github.com/weiliangchun/JavaCode/tree/master/ssm/1-2spring_transaction
SSM学习路径分为4个阶段
- 战斗伊始——Spring
- 转战阵地——SpringMVC
- 再下一城——MyBatis
- 终极目标——整合案例
战斗伊始——Spring
1-2 Spring事务管理
概念介绍
事务回顾
什么是事务
事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败- 事务的特性
- 原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
- 一致性:事务前后数据的完整性必须保持一致
- 隔离性:多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离
- 持久性:一个事务一旦被提交,它对数据中数据的改变就是永久性的,即使shujuk发生故障也不应该对其有任何影响
事务的API介绍
Spring接口介绍
Spring事务管理高层抽象主要包括三个接口:
- PlatformTransactionManager 事务管理器
- TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
- TransactionStatus 事务具体运行状态
事务管理器 PlatformTransactionManager
- Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现
| 事务 | 说明 |
|---|---|
| org.springframework.jdbc.datasource.DataSourceTransactionManager | 使用Spring JDBC或iBatis进行持久化数据时使用 |
| org.springframework.orm.hibernate3.HibernateTransactionManager | 使用Hibernate3.0版本进行持久化数据时使用 |
| org.springframework.orm.jpa.JpaTransactionManager | 使用JPA进行持久化时使用 |
| org.springframwork.jdo.JdoTransactionManager | 当持久化机制是Jdo时使用 |
| org.springframwork.transaction.jta.JtaTransactionManager | 使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用 |
事务定义信息 TransactionDefinition
- 如果不考虑隔离性,会引发安全问题如下
- 脏读: 一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的
- 不可重复读: 在同一个事务中,多次读取同一数据返回的结果有所不同
- 幻读: 一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。在后来的查询中,第一个事务就会发现有些原来没有的记录
- 事务隔离级别
| 隔离级别 | 含义 |
|---|---|
| DEFAULT | 使用后端数据库默认的隔离级别(spring中的选择项) |
| READ_UNCOMMITTED | 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读 |
| READ_COMMITTED | 允许在并发事务已经提交后读取。可防止脏读,但幻读和不可重复读仍可发生 |
| REPEATABLE_READ | 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生 |
| SERIALIZABLE | 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它的典型的完全锁定在事务中涉及的数据表来完成的 |
mysql默认采用REPEATABLE_READ隔离级别
Oracle默认采用READ_COMMITTED隔离级别
- 事务传播行为
| 事务传播行为类型 | 说明 |
|---|---|
| PROPAGATION_REQUIRED | 支持当前事务,如果不存在,就新建一个 |
| PROPAGATION_SUPPORTS | 支持当前事务,如果不存在,就不使用事务 |
| PROPAGATION_ANDATORY | 支持当前事务,如果不存在,抛出异常 |
| PROPAGATION_REQUIRES_NEW | 如果有事务存在,挂起当前事务,创建一个新的事务 |
| PROPAGATION_NOT_SUPPORTED | 以非事务方式运行,如果有事务存在,挂起当前事务 |
| PROPAGATION_NEVER | 以非事务方式运行,如果有事务存在,抛出异常 |
| PROPAGATION_NESTED | 如果当前事务存在,则嵌套事务执行 |
Spring 事务管理
Spring 支持两种方式事务管理
- 编程式的事务管理
- 在实际应用中很少使用
- 通过TransactionTemplate手动管理事务
- 使用XML配置声明式事务
- 开发中推荐使用(代码侵入性最小)
- Spring的声明式事务是通过AOP实现的
转账案例
- 创建数据表account
CREATE TABLE account(
-> id INT(11) NOT NULL AUTO_INCREMENT,
-> name VARCHAR(20) NOT NULL,
-> money DOUBLE DEFAULT NULL,
-> PRIMARY KEY(id)
-> )ENGINE=
InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO account VALUES('1','aaa','1000');
INSERT INTO account VALUES('2','bbb','1000');
INSERT INTO account VALUES('3','ccc','1000');
- 创建maven工程
- 添加依赖
- 在src/main/resources目录编写配置:applicationContext.xml log4j.properties jdbc.properties
- 编写DAO注入 注入JdbcTemplate
package com.spring.demo1.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/*
* 转账案例的DAO层的实现类
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
/**
* @param out : 转出账号
* @param money :转账金额
*/
@Override
public void outMoney(String out, Double money) {
String sql = "update account set money = money - ? where name = ?";
this.getJdbcTemplate().update(sql,money,out);
}
/**
* @param in : 转入账号
* @param money : 转账金额
*/
@Override
public void inMoney(String in, Double money) {
String sql = "update account set money = money + ? where name = ?";
this.getJdbcTemplate().update(sql,money,in);
}
}
- 编写service注入DAO
package com.spring.demo1.service;
import com.spring.demo1.dao.AccountDao;
/*
* 转账案例的业务层实现类
*/
public class AccountServiceImpl implements AccountService {
//注入转账的DAO
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
/**
* @param out : 转出账号
* @param in : 转入账号
* @param money : 转账金额
*/
@Override
public void transfer(String out, String in, Double money) {
//aaa向bbb转账200元
accountDao.outMoney("aaa", 200);
int i = 1 / 0;
accountDao.inMoney("bbb", 200);
}
}
- 配置applicationContext.xml
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置业务层的类 -->
<bean id="accountService" class="com.spring.demo1.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!-- 配置DAO的类 -->
<bean id="accountDao" class="com.spring.demo1.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
编程式事务管理
- 在AccountService中使用TransactionTemplate
- TransactionTemplate依赖DataSourceTransactionManager
- DataSourceTransactionManager依赖DataSource构造
<bean id="accountService" class="cn.java.service.AccountService">
<property name="accountDAO" ref="accountDAO"/>
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
package com.spring.demo1.service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.spring.demo1.dao.AccountDao;
/*
* 转账案例的业务层实现类
*/
public class AccountServiceImpl implements AccountService {
//注入转账的DAO
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
//注入事务管理模版
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
/**
* @param out : 转出账号
* @param in : 转入账号
* @param money : 转账金额
*/
@Override
public void transfer(final String out, final String in, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
int i = 1 / 0;
accountDao.inMoney(in, money);
}
});
}
}
声明式事务管理
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置业务层的代理 -->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置目标对象 -->
<property name="target" ref="accountService"/>
<!-- 注入事务管理器 -->
<property name="transactionManager" ref="transactionManager"/>
<!-- 注入事务属性 -->
<property name="transactionAttributes">
<props>
<!--
prop的格式
* PROPAGATION : 事务的传播行为
* ISOLATION : 事务的隔离级别
* readOnly : 只读(不可以进行修改,插入,删除)
* -Exception : 发生哪些异常回滚事务
* +Exception : 发生哪些异常事务不回滚
-->
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
@Resource(name="accountServiceProxy")
private AccountService accountService;
@Test
/*
* 转账案例
*/
public void test1() {
accountService.transfer("aaa", "bbb", 200d);
}
使用XML配置声明式事务 基于tx/aop
- 引入aop和tx命名空间
<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">
<!-- 配置事务管理器 -->
<bean id="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="transfer" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.spring.demo3.service.AccountService+.*(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>
使用注解配置声明式事务
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
//需要声明事务的类上加注解
@Transactional
public class AccountServiceImpl implements AccountService {
...
}
总结
Spring将事务管理分成了两类:
编程式事务管理
手动编写代码进行事务管理(很少使用)声明式事务管理
1.基于TransactionProxyFactoryBean的方式(很少使用)需要为每个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强
2.基于AspectJ的XML方式(常用)一旦配置好,类上不需要添加任何东西
3.基于注解方式在(常用)配置简单。需要在业务层类上添加@Transactionanl的注解
SSM(spring mvc+spring+mybatis)学习路径——1-2、spring事务管理的更多相关文章
- SSM(spring mvc+spring+mybatis)学习路径——2-2、spring MVC拦截器
目录 2-2 Spring MVC拦截器 第一章 概述 第二章 Spring mvc拦截器的实现 2-1 拦截器的工作原理 2-2 拦截器的实现 2-3 拦截器的方法介绍 2-4 多个拦截器应用 2- ...
- SSM(spring mvc+spring+mybatis)学习路径——2-1、spring MVC入门
目录 2-1 Spring MVC起步 一.回顾Servlet 二.SpringMVC简介 三.搭建SpringMVC第一个案例 四.简单流程及配置 五.使用注解开发Controller 六.参数绑定 ...
- SSM(spring mvc+spring+mybatis)学习路径——1-1、spring入门篇
目录 1-1 Spring入门篇 专题一.IOC 接口及面向接口编程 什么是IOC Spring的Bean配置 Bean的初始化 Spring的常用注入方式 专题二.Bean Bean配置项 Bean ...
- SSM 三大框架系列:Spring 5 + Spring MVC 5 + MyBatis 3.5 整合(附源码)
之前整理了一下新版本的 SSM 三大框架,这篇文章是关于它的整合过程和项目源码,版本号分别为:Spring 5.2.2.RELEASE.SpringMVC 5.2.2.RELEASE.MyBatis ...
- Spring、Spring MVC、MyBatis
Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. Sp ...
- 转载 Spring、Spring MVC、MyBatis整合文件配置详解
Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. ...
- 搭建Spring、Spring MVC、Mybatis和Freemarker
搭建Spring.Spring MVC.Mybatis和Freemarker 1.pom文件 <project xmlns="http://maven.apache.org/POM/4 ...
- IDEA下创建Maven项目,并整合使用Spring、Spring MVC、Mybatis框架
项目创建 本项目使用的是IDEA 2016创建. 首先电脑安装Maven,接着打开IDEA新建一个project,选择Maven,选择图中所选项,下一步. 填写好GroupId和ArtifactId, ...
- spring MVC、mybatis配置读写分离
spring MVC.mybatis配置读写分离 1.环境: 3台数据库机器,一个master,二台slave,分别为slave1,slave2 2.要实现的目标: ①使数据写入到master ②读数 ...
随机推荐
- MVVMLight消息通知实现机制详解(二)
接上文 MVVMLight消息通知实现机制详解(一) 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型.Key值.Action.Target(订阅对象本身) 在发生订阅事 ...
- PCB CE工具取Genesis JOB与STEP内存地址 方法分享
今天无意中在硬盘上找到了<CE工具取Genesis JOB与STEP内存地址 >视频, 这是2013年初由郭兄(永明)远程时录制的一段视频,特别感谢郭兄指引与帮助, 想当初要不是你推出全行 ...
- 元素类型以及overflow,white-space等属性
1:预格式化标签:<pre></pre>2:overflow属性="visible/hidden(隐藏)"/scroll/auto(自动)/inherit; ...
- Akka源码分析-local-DeathWatch
生命周期监控,也就是死亡监控,是akka编程中常用的机制.比如我们有了某个actor的ActorRef之后,希望在该actor死亡之后收到响应的消息,此时我们就可以使用watch函数达到这一目的. c ...
- ERROR: While executing gem ... (Errno::EPERM) Operation not permitted - /usr/bin/pod
因为突然要用到cocospod,突然发现在使用pod install的时候出现 -bash: pod: command not found 我去-不知道为什么,然后我就想重新安装下cocospod,在 ...
- 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)
上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...
- Codeforces 612D 前缀和处理区间问题
传送门:http://codeforces.com/problemset/problem/612/D (转载请注明出处谢谢) 题意: 给出数字n和k,n表示接下来将输入n个在x轴上的闭区间[li,ri ...
- 347 Top K Frequent Elements 前K个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素.例如,给定数组 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2].注意: 你可以假设给定的 k 总是合理的,1 ≤ k ...
- jQuery——多库共存
多库共存:jQuery占用了$ 和jQuery这两个变量.当在同一个页面中引用了jQuery这个js库,并且引用的其他库(或者其他版本的jQuery库)中也用到了$或者jQuery这两个变量,那么,要 ...
- win10 打开chm文件内容空白如何解决
win10 打开chm文件内容空白如何解决 .CHM文件是非常常见的帮助文件格式.由于其便携性,很多小说或杂志也会采用chm格式.win7/win8.1/win10系统,由于采用了UAC,致使原本在x ...