本文源码:GitHub·点这里 || GitEE·点这里

一、Spring事务管理

1、基础描述

Spring事务管理的本质就是封装了数据库对事务支持的操作,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交和回滚。

Connection conn = DriverManager.getConnection();
try {
// 自动提交设置为false
conn.setAutoCommit(false);
// 执行增删改查操作
// 当操作成功后手动提交
conn.commit();
} catch (Exception e) {
// 出现异常,回滚所有操作
conn.rollback();
e.printStackTrace();
} finally {
conn.colse();
}

2、事务常见概念

  • 事务

事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部成功,要么全部不成功。

  • 特性:ACID
原子性(Atomicity):事务中的多个操作要么都成功要么都失败
一致性(consistency):事务的执行的前后数据的完整性保持一致
隔离性(isolation):事务执行的过程中,不应该受到其他事务的干扰
持久性(durability):事务一旦结束,数据就持久到数据库
  • 隔离问题

脏读:一个事务读到另一个事务没有提交的数据

不可重复读:一个事务前后多次读取相同数据,数据内容不一致,update场景问题

虚读(幻读):一个事务前后多次读取,数据总量不一致,insert场景问题

  • 隔离级别

read uncommitted:

事务可以读取另一个未提交事务的数据。

read committed

事务要等另一个事务提交后才能读取数据,解决脏读。

repeatable read

在开始读取数据时,事务开启,不再允许修改操作,解决:脏读、不可重复读。

serializable

最高事务隔离级别,事务串行化顺序执行,解决脏读、不可重复读、幻读。但是效率低下,耗数据库性能。

3、事务管理API描述

  • PlatformTransactionManager

平台事务管理器,Spring管理事务,必须使用事务管理器进行事务配置时,核心方法:获取事务,提交事务,回滚事务。

  • TransactionDefinition

该对象封装事务详情(事务定义、事务属性),例如:隔离级别、是否只读、超时时间 等。

  • TransactionStatus

用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。Spring底层根据状态进行相应操作。

4、事务案例SQL语句

CREATE TABLE user_account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
money INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;;
INSERT INTO user_account(username,money) VALUES('jack','5000');
INSERT INTO user_account(username,money) VALUES('tom','5000');
SELECT * FROM user_account ;

二、编程式事务管理

1、核心配置文件

<!-- 配置事物管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 创建事物模板 -->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager" />
</bean>
<!-- 配置转账接口 -->
<bean id="userAccountService"
class="com.spring.mvc.service.impl.UserAccountServiceImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="transactionTemplate" ref="transactionTemplate" />
</bean>

2、演示案例

@Service
public class UserAccountServiceImpl extends JdbcDaoSupport implements UserAccountService {
// 注入事物模板
private TransactionTemplate transactionTemplate ;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
public void remittance(String remitTer, String receiver, int money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus arg0) {
outMoney(remitTer,money);
// System.out.println(1/0);
innerMoney(receiver,money);
}
});
}
private void outMoney (String remitTer, int money){
String outSql = "update user_account set money = money - ? where username = ?";
this.getJdbcTemplate().update(outSql, money ,remitTer);
}
private void innerMoney (String receiver, int money){
String inSql = "update user_account set money = money + ? where username = ?";
this.getJdbcTemplate().update(inSql, money,receiver);
}
}

三、事务代理工厂

1、核心配置

<!-- 配置转账接口 -->
<bean id="userAccountService01"
class="com.spring.mvc.service.impl.UserAccountServiceImpl01">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 配置事务代理工厂 -->
<bean id="proxyAccountService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces" value="com.spring.mvc.service.UserAccountService01" />
<property name="target" ref="userAccountService01" />
<property name="transactionManager" ref="txManager" />
<property name="transactionAttributes">
<props>
<!-- 默认传播行为、隔离级别 -->
<prop key="remittance">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
<!-- 异常仍然提交事务
<prop key="remittance">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.Exception</prop>
-->
</props>
</property>
</bean>

配置说明:

  • proxyInterfaces 代理接口
  • target 代理目标类
  • transactionManager 事务管理器
  • transactionAttributes 事务属性(事务详情)
  • prop.key 指定方法使用当前事务配置

事务行为:

  • PROPAGATION 传播行为
  • ISOLATION 隔离级别
  • readOnly 是否只读
  • -Exception 异常回滚
  • +Exception 异常提交

2、演示案例

@Service
public class UserAccountServiceImpl01 extends JdbcDaoSupport implements UserAccountService01 {
@Override
public void remittance(String remitTer, String receiver, int money) {
outMoney(remitTer,money);
System.out.println(1/0);
innerMoney(receiver,money);
}
private void outMoney (String remitTer, int money){
String outSql = "update user_account set money = money - ? where username = ?";
this.getJdbcTemplate().update(outSql, money ,remitTer);
}
private void innerMoney (String receiver, int money){
String inSql = "update user_account set money = money + ? where username = ?";
this.getJdbcTemplate().update(inSql, money,receiver);
}
}

3、测试代码

public class Tx_Test_02 {
@Test
public void test1 (){
String xmlPath = "spring-jdbc-tx-02.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
UserAccountService01 accountService = (UserAccountService01)
context.getBean("proxyAccountService");
accountService.remittance("jack","tom",1000);
}
}

四、XML配置事务

首先配置事务管理器,然后配置事务属性,最后基于AOP编程配置事务切入点。

1、核心配置

<!-- 配置事物管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置转账接口 -->
<bean id="userAccountService01"
class="com.spring.mvc.service.impl.UserAccountServiceImpl01">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 配置事物详情 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="remittance"
propagation="REQUIRED"
isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!-- 事务切入点,基于AOP编程 -->
<aop:config>
<aop:advisor
advice-ref="txAdvice"
pointcut="execution(* com.spring.mvc.service.UserAccountService01.*(..))"/>
</aop:config>

五、基于事务注解

配置事务管理器,并启动事务注解的支持,在目标类或目标方法添加@Transactional核心注解即可。

1、核心配置

<!-- 配置事物管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 支持事务注解 -->
<tx:annotation-driven transaction-manager="txManager" />

2、注解用法

注解写在接口方法上,或者接口实现的方法上效果一样。

public interface UserAccountService02 {
@Transactional(rollbackFor = Exception.class)
void remittance(String remitTer, String receiver, int money) ;
}

六、源代码地址

GitHub·地址
https://github.com/cicadasmile/spring-mvc-parent
GitEE·地址
https://gitee.com/cicadasmile/spring-mvc-parent

Spring 框架基础(05):事务管理机制,和实现方式的更多相关文章

  1. Spring框架——JDBC与事务管理

    JDBC JDBCTemplate简介 XML配置JDBCTemplate 简化JDBC模板查询 事务管理 事务简介 Spring中的事务管理器 Spring中的事务管理器的不同实现 用事务通知声明式 ...

  2. Spring总结九:事务管理机制

    何为事务 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常由高级数据库操纵语言或编程语言(如SQL ...

  3. 12 Spring框架 SpringDAO的事务管理

    上一节我们说过Spring对DAO的两个支持分为两个知识点,一个是jdbc模板,另一个是事务管理. 事务是数据库中的概念,但是在一般情况下我们需要将事务提到业务层次,这样能够使得业务具有事务的特性,来 ...

  4. Spring 框架系列之事务管理

    1.事务回顾 (1).什么是事务: 事务是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败. (2).事务特性(ACID) 原子性 :强调事务的不可分割 一致性 :事务的执行的 ...

  5. Spring Transaction + MyBatis SqlSession事务管理机制[marked]

  6. Spring入门5.事务管理机制

    Spring入门5.事务管理机制 20131126 代码下载 : 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 回顾之前的知识,Spring 最为核心的两个部分 ...

  7. Spring事务管理机制的实现原理-动态代理

    之前在做项目中遇到spring无法进行事务代理问题,最后发现是因为没有写接口,原因当时明白了,看到这篇文章写的清楚些,转过来 我们先来分析一下Spring事务管理机制的实现原理.由于Spring内置A ...

  8. spring 事务管理机制

    1. spring 事务管理抽象 spring 的事务策略机制的核心就是 org.springframework.transaction.PlatformTransactionManager 接口. ...

  9. Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制

    Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制 201311.27 代码下载 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 前言 ...

随机推荐

  1. QQ聊天记录分析

    今天我们用R语言来处理一下.我们会用到一下技术:. (1)正则表达式 (2)词频统计 (3)文本可视化 (4)ggplot2绘图 (5)中文分词 一.数据处理 首先我们要讲QQ聊天记录导出成txt文件 ...

  2. 在ArangoDB中实现connectedcomponents算法

    操作环境: tool:ArangoDB 3.3.13 操作系统:Debian 7.2.0-20 概念: Connected Components即连通体算法.用id标注图中每个连通体,将连通体中序号最 ...

  3. 第五篇 Flask 中内置的 Session

    Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from ...

  4. 身份证号码验证算法(php和js实现)

    原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=21126994&id=3938244 http://www.jb ...

  5. Topshelf+Quartz在.Net Core框架下的实现

    在我们日常开发工作中,经常会运用到Quartz+Topshelf组件的组合来开发一些定时任务.那么在.Net Core下如何去使用呢?我自己尝试搭建了一个测试项目,过程中遇到了以下一些问题: Quar ...

  6. 在虚拟机上的关于FTP FTP访问模式(虚拟用户模式)

    首先你要有vsftpd服务 可以先去yum中下载(当然你要有本地yum仓库) 输入命令: yum  install  vsftpd 下载完成之后打开vsftpd服务 输入命令:systemctl   ...

  7. opacity层叠问题

    使用了position属性值为 absolute.relative 的层,将会比普通层更高层次.使用了小于1的opacity属性的层,也比普通层更高层次并且和指定 position 的层同层,但是不支 ...

  8. 文件 File

    文件 1. 文件的一些常用方法 package com.ljw.study; import java.io.File; import java.util.Arrays; import java.uti ...

  9. group 状压dp

    应某些人要求,我把标签删掉了 这是一道好题. 一看$c<=16$果断状压,但是怎么压? 一个很显然的思路是,枚举上下两层的状态,每一层的状态极限有$C(c,c/2)$,c=16的时候有13000 ...

  10. 思科获取DHCP过程

    主机如何获取DHCP的过程? 地址请求: 客户端发布一个DHCP请求信息,该信息会发给网内所有主机,非DHCP服务器会丢弃信息. 地址提供: DHCP服务端收到该信息后,会从地址池内挑选一个未被使用的 ...