07_Spring事务处理
一.事务概述
数据库的事务: 事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等。事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出现了差错,比如有一条SQL语句没有执行成功,那么这一组操作都将全部回滚。
事务的四大特性:
atomic(原子性):要么都发生,要么都不发生。
consistent(一致性):数据应该不被破坏。
isolate(隔离性):用户间操作不相混淆
durable(持久性):永久保存,例如保存到数据库中等
编程式事务管理
通过程序代码来控制你的事务何时开始,何时结束等,结果是控制的颗粒度更细,但需要手写程序,另外在团队合作开发时,会出现事务管理混乱。
注意:如果使用Spring, 我们就不再需要手工控制事务
声明式事务管理
在Spring中,你只需要在Spring配置文件中做一些配置,即可将数据库的访问纳入到事务管理中,解除了和代码的耦合, 这是对应用代码影响最小的选择。当你不需要事务管理的时候,可以直接从Spring配置文件中移除该设置。
Spring事务管理高层抽象主要包括3个接口
1.PlatformTransactionManager(事务管理器)

Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现,spring的事务管理器: spring没有直接管理事务,只是开发了事务管理器调用第三方组件完成事务控制。
|
事务 |
说明 |
|
org.springframework.jdbc.datasource.DataSourceTransactionManager |
使用Spring JDBC或iBatis 进行持久化数据时使用 |
|
org.springframework.orm.hibernate3.HibernateTransactionManager |
使用Hibernate3.0版本进行持久化数据时使用 |
|
org.springframework.orm.jpa.JpaTransactionManager |
使用JPA进行持久化时使用 |
|
org.springframework.jdo.JdoTransactionManager |
当持久化机制是Jdo时使用 |
|
org.springframework.transaction.jta.JtaTransactionManager |
使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用 |
2.TransactionDefinition(事务定义)
ISOLation_XXX:事务隔离级别.
PROPAGATION_XXX:事务的传播行为.

3.TransactionStatus(事务具体运行状态)

事务的传播行为
Spring控制事务的方式:spring控制事务是以bean组件的函数为单位的,如果一个函数正常执行完毕,该函数内的全部数据库操作按照一次事务提交,如果抛出异常,全部回滚。
事务的传播策略
如两个bean组件都由spring控制事务,且组件的函数之间存在调用关系,即(bean1 函数a 调用了 bean2 函数b),spring提供了一组配置方式供开发者选择,这些配置方式称为事务的传播策略。
数据库的隔壁级别
脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。
幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。
|
隔离级别 |
含义 |
|
DEFAULT |
使用后端数据库默认的隔离级别(spring中的的选择项) |
|
READ_UNCOMMITED |
允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读 |
|
READ_COMMITTED |
允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生 |
|
REPEATABLE_READ |
对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。 |
|
SERIALIZABLE |
完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。 |
一般使用,去头去尾
只读事务与读写事务
只读事务与读写事务:
与所访问的数据库以及数据库驱动程序相关,并不一定是一个强制选项(例如在只读事务中去更新事务时允许的)。但若在事务中声明了只读事务,将会暗示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,不记录回滚日志等,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。
使用场景:
只读事务:单纯的数据库查询
读写事务:对数据进行修改的操作。
配置声明式事务控制
1.在配置文件头信息上增加tx命名空间与tx.xsd:声明式事务控制需要引入tx标签,因此要引入此xsd文件。
2.配置事务控制管理器:
3.配置事务通知:配置哪些函数委托spring进行事务管理,以及事务管理的隔离级别、传播行为、是否只读事务属性。建议大家在需要更新数据的函数上配置隔离级别为数据库默认级别,传播行为采用required,读写事务。而只是查询的函数使用只读事务,效率更高
4.配置事务的切入点:也就是spring的哪些组件要配置事务通知。
在spring的三层架构中,建议把事务控制放在service层。
实例:银行转账
AccountDao.java
public interface AccountDao {
//存钱
void addMoney(Integer id,Double money);
//取钱
void withDrawMoney(Integer id,Double money);
}
AccountDaoImpl.java
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
@Override
public void addMoney(Integer id, Double money) {
String sql = "update Account set money = money + ? where id = ?";
getJdbcTemplate().update(sql,money,id);
}
@Override
public void withDrawMoney(Integer id, Double money) {
String sql = "update Account set money = money - ? where id = ?";
getJdbcTemplate().update(sql,money,id);
}
}
AccountService.java
public interface AccountService {
//转账
public void transfromMoney(Integer from_id, Double money,Integer to_id);
}
AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Override
public void transfromMoney(Integer from_id, Double money,Integer to_id) {
//取钱
accountDao.withDrawMoney(from_id,money);
//存钱
accountDao.addMoney(to_id,money);
}
public AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
jdbc.properties
jdbc.driverClass=com.jdbc.mysql.Driver
jdbc.jdbcUrl=jdbc:mysql:///crm
jdbc.user=root
jdbc.password=123456
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
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-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
<!--1 读取属性文件方式<二> -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<!--2 c3p0数据源 (连接池)-->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 2.5 创建 jdbcTemplate 不需要了,因为我们继承了JdbcDaoSupport -->
<!-- <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> -->
<!--3 AccountDao对象 -->
<bean name="accountDao" class="com.icss.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--4 AccountService对象 -->
<bean name="accountService" class="com.icss.service.AccountServiceImpl">
<property name="ad" ref="accountDao"></property>
</bean>
<!-- 声明式事务处理配置 -->
<!--1 创建核心事务管理,封装了所有事务的操作,事务也依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2 事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- name:指方法的名称,*表示通配符
isolation:隔离级别
1 读未提交
2 读己提交 oracle(默认)
4 可重复读 mysql(默认)
8 串行化
propagation:传播行为(必须=REQUIRED 99.9999%)
read-only:只读
-->
<tx:method name="add*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="query*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="trans*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
<!--3织入将我们通知织入目标对象中 -->
<aop:config>
<!-- 切点 -->
<aop:pointcut expression="execution(* com.service.*ServiceImpl.*(..))" id="pc"/>
<!-- 切面 (通知+切点)-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
</beans>
结论:声明式事务配置步骤
1.创建核心事物管理,分装了所有事物操作,事物也依赖连接池
2.配置事物通知
3:织入:将通知织入到目标对象中
07_Spring事务处理的更多相关文章
- In-Memory:内存优化表的事务处理
内存优化表(Memory-Optimized Table,简称MOT)使用乐观策略(optimistic approach)实现事务的并发控制,在读取MOT时,使用多行版本化(Multi-Row ve ...
- 读书笔记--SQL必知必会20--管理事务处理
20.1 事务处理 使用事务处理(transaction processing),通过确保成批的SQL操作要么完全执行,要么完全不执行,来维护数据库的完整性. 如果没有错误发生,整组语句提交给数据库表 ...
- EntityFramework 事务处理
默认情况下,当EF调用SaveChanges()时,会把生成的所有SQL命令“包”到一个“事务(transaction)”中,只要有一个数据更新操作失败,整个事务将回滚. 在多数情况下,如果你总在数据 ...
- Java事务处理
Java事务处理总结 一.什么是Java事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(co ...
- PHP与MYSQL事务处理
/*MYSQL的事务处理主要有两种方法.1.用begin,rollback,commit来实现begin 开始一个事务rollback 事务回滚commit 事务确认2.直接用set来改变mysql的 ...
- 已经过事务处理的 MSMQ 绑定(转载)
https://msdn.microsoft.com/zh-cn/biztalk/ms751493 本示例演示如何使用消息队列 (MSMQ) 执行已经过事务处理的排队通信. 注意 本主题的末尾介绍了此 ...
- SQLite剖析之事务处理技术
前言 事务处理是DBMS中最关键的技术,对SQLite也一样,它涉及到并发控制,以及故障恢复等等.在数据库中使用事务可以保证数据的统一和完整性,同时也可以提高效率.假设需要在一张表内一次插入20个人的 ...
- PHP系统声明式事务处理
转自:http://www.jianshu.com/p/34261804bc45 1.数据库事务 事务(Transaction)是并发控制的基本单位.所谓的事务,它是一个操作序列,这些操作要么都执行, ...
- 事务处理-回滚(转账操作)(转自http://www.cnblogs.com/void-m/p/6143540.html)
JDBC事务处理-四大原则 原子性一致性隔离性持久性 第一步:实现转账操作 假设在账户中,盖伦有余额5000元,赵信有余额2000元, 盖伦要向赵信转账1000元. 1 2 3 4 5 6 7 8 9 ...
随机推荐
- go 函数和流程控制
if/else分支判断 基本结构如下: if condition1 { } if condition1 { } else { } if condition1 { } else if condition ...
- 基于第三方开源库的OPC服务器开发指南(1)——OPC与DCOM
事儿太多,好多事情并不以我的意志为转移,原想沉下心好好研究.学习图像识别,继续丰富我的机器视觉库,并继续<机器视觉及图像处理系列>博文的更新,但计划没有变化快,好多项目要完成,只好耽搁下来 ...
- winsock 服务器代码(不建议win服务器listen防火墙会禁止外部访问的)
int SessionBase::ServerSock() { /* 4 * WSADATA是个结构体,在WSAStartup中被填充. 5 * WSAStartup为调用WinSock准备初始化的工 ...
- 帆软报表PC端实施报表心得体会
1.报表制作完成后,预览时自动显示查询内容,在控件处设置: 2.求一列数据的最小值(除去0),并对最小值字体加粗标绿,需要对对应单元格设置条件属性,并插入公式:C6 = min(greparray(C ...
- spring整合Quartz框架过程,大家可以参考下
这篇文章详细介绍了spring集成quartz框架流程,通过示例代码进行了详细说明,对学习或任务有参考学习价值,并可供需要的朋友参考. 1.quartz框架简介(m.0831jl.com) quart ...
- HashMap 什么时候进行扩容呢
HashMap扩容: 当HashMap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在A ...
- Docker系列(六):Docker网络机制(下)
Linux Namespace详解 namespace:是一个空间,空间里可以放进程,文件系统,账号,网络等,某个资源被放到namespace之后 别人就看不到他了. 可以看到有两个namespace ...
- 使用JDK自带功能,实现一个简单的Web Service接口发布
万事开头难,本篇文章的目的就是使用JDK自带的功能,实现一个最简单的Web Service接口的发布. 下图是项目的组成,主要有三个部分,一个接口(WS),一个接口的实现类(WSImp),还有一个接口 ...
- 总结windows cmd 查看进程,端口,硬盘信息
1.查看window所有进程 tasklist 2.查看windows所占用的进程号 tasklist|findstr 1916 3.杀死进程,进程pid taskkill /f /pid 10156 ...
- HYNB Round 15: PKU Campus 2019
HYNB Round 15: PKU Campus 2019 C. Parade 题意 将平面上n*2个点安排在长度为n的两行上. 做法 首先可以忽略每个点之间的影响,只用考虑匹配即可 然后把所以点归 ...