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 ...
随机推荐
- iOS开发系列-Runtime运用场景
概述 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的. 调用runtimeAPI需要导入都文件#impor ...
- u-boot 的介绍及系统结构
u-boot 介绍 Uboot 是德国 DENX 小组的开发用于多种嵌入式 CPU 的 bootloader 程序, UBoot 不仅仅支持嵌入式 Linux 系统的引导,当前,它还支持 Net ...
- TwainCapabilities
Twain Capabilities 2013年10月15日 ⁄ 综合 ⁄ 共 6098字 ⁄ 字号 小 中 大 ⁄ 评论关闭 转自:http://blog.163.com/lvan100@yeah/ ...
- dev设置子窗体的初始位置,grid控件表头的属性设置
当在父窗体上弹出子窗体时,一般设置子窗体的初始位置是居中, //在需要展示子窗体的父窗体上写这段,注意必须设置在show方法之前Form2 f2 = new Form2(); f2.MdiParent ...
- Educational Codeforces Round 27 D. Driving Test
单调栈 题意看了半天... #include <cstdio> #include <cstdlib> #include <cmath> #include <c ...
- BigDecimal踩过的大坑
通常Java中涉及金钱相关的计算为了保持精度,会采用BigDecimal来实现,但是BigDecimal中创建BigDecimal类对象的时候,如果使用直接new的话,必须是String类型的参数,否 ...
- LUOGU P4322 [JSOI2016]最佳团体(0/1分数规划+树形背包)
传送门 解题思路 一道0/1分数规划+树上背包,两个应该都挺裸的,话说我常数为何如此之大..不吸氧洛谷过不了啊. 代码 #include<iostream> #include<cst ...
- POJ 2104:K-th Number 整体二分
感觉整体二分是个很有趣的东西. 在别人的博客上看到一句话 对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了 树套树写了一天还是WA着,调得焦头烂额,所以决定学cd ...
- python和go对比字符串的链式处理
一.什么是链式处理 对数据的操作进行多步骤的处理称为链式处理,链式处理器是一种常见的编程设计,链式处理的开发思想将数据和操作拆分,解耦,让开发者可以根据自己的技术优势和需求,进行系统开发,同时将自己的 ...
- Java学习之继承关系内存分配
假设有C继承B,B继承A; 继承会继承除private修饰的成员变量,方法.但不会继承构造器. 所以调用被继承下来的方法时,不需要指明主调者,但是调用构造器时,就需要指明主调者,那就是super.如果 ...