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 ...
随机推荐
- 2019牛客暑期多校训练营(第八场)I-Inner World DFS序+主席树(扫描线也可)
题目传送门 题意:初始有n棵树,每棵树都只有1个n号节点,现在有m次添加操作,每次操作是将$[l,r]$范围内的树的$u$节点后面添加一个$v$节点.每个v节点只会被添加一次. 然后是q次询问,输出$ ...
- Android开发 ImageView开发记录
改变图片的着色 默认是这个方法 /** * 为图像设置着色选项. Assumes * {@link PorterDuff.Mode#SRC_ATOP} blending mode. * * @para ...
- canvas插入图片设置背景,渐变
##在canvas中插入图片(需要image对象) 1.canvas操作图片时,必须要等图片加载完才能操作 2.drawImage(image, x, y, width, height) 其中 ima ...
- 【JZOJ4811】排队
description analysis 堆\(+\)树上倍增 考虑后序遍历搞出\(dfs\)序,那么要填肯定是从\(dfs\)序开始填 把每个点是序里第几位看成优先级,用小根堆来维护当前空着的优先级 ...
- Windows mkdir
创建目录. MKDIR [drive:]pathMD [drive:]path 如果命令扩展被启用,MKDIR 会如下改变: 如果需要,MKDIR 会在路径中创建中级目录.例如: 假设 \a 不存在, ...
- CSS案例3(在线教育网站)
案例练习目的是总结以前的css和html 还有ps的使用. 制作步骤: 准备相关文件.(内部样式表) html文件(index.html) 图片文件 准备CSS 初始化. 书写结构和样式 确定版心(是 ...
- SpringBoot_04_SpringBoot对ssm的整合
1.在SpringBoot框架下对ssm进行整合 2.搭建一个web的SpringBoot框架 2.1添加pom.xml坐标(需要加上SpringBoot对jsp的支持,和对资源文件位置的说明) &l ...
- springboot下自定义配置文件,并在项目里读取的方法
首先 pom文件引入springboot文件处理器 <dependency> <groupId>org.springframework.boot</groupId> ...
- py测试一个Socket实例
本实例旨在了解py和socket的一些相关知识. 1.服务器端搭建py监听程序. 在客户端搭建python,linux默认自带了python2.7,先不管安装了. 接着编写socket程序,可以在本地 ...
- MyBatis基础-CRUD
一.mybatis 环境搭建步骤 第一步:创建 maven 工程第二步:导入坐标第三步:编写必要代码(实体类和持久层接口)第四步:编写 SqlMapConfig.xml第五步:编写映射配置文件第六步 ...