内容可能存在MK版本兼容原因显示异常,可以异步我的github上的readme观看。该篇源码和readme地址:https://github.com/weiliangchun/JavaCode/tree/master/ssm/1-2spring_transaction

SSM学习路径分为4个阶段

  • 战斗伊始——Spring
  • 转战阵地——SpringMVC
  • 再下一城——MyBatis
  • 终极目标——整合案例

战斗伊始——Spring

1-2 Spring事务管理

概念介绍

事务回顾

  1. 什么是事务
    事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败

  2. 事务的特性
  • 原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
  • 一致性:事务前后数据的完整性必须保持一致
  • 隔离性:多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离
  • 持久性:一个事务一旦被提交,它对数据中数据的改变就是永久性的,即使shujuk发生故障也不应该对其有任何影响

事务的API介绍

Spring接口介绍

Spring事务管理高层抽象主要包括三个接口:

  1. PlatformTransactionManager 事务管理器
  2. TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
  3. 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

  • 如果不考虑隔离性,会引发安全问题如下
  1. 脏读: 一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的
  2. 不可重复读: 在同一个事务中,多次读取同一数据返回的结果有所不同
  3. 幻读: 一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。在后来的查询中,第一个事务就会发现有些原来没有的记录
  • 事务隔离级别
隔离级别 含义
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 支持两种方式事务管理

  1. 编程式的事务管理
  • 在实际应用中很少使用
  • 通过TransactionTemplate手动管理事务
  1. 使用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事务管理的更多相关文章

  1. SSM(spring mvc+spring+mybatis)学习路径——2-2、spring MVC拦截器

    目录 2-2 Spring MVC拦截器 第一章 概述 第二章 Spring mvc拦截器的实现 2-1 拦截器的工作原理 2-2 拦截器的实现 2-3 拦截器的方法介绍 2-4 多个拦截器应用 2- ...

  2. SSM(spring mvc+spring+mybatis)学习路径——2-1、spring MVC入门

    目录 2-1 Spring MVC起步 一.回顾Servlet 二.SpringMVC简介 三.搭建SpringMVC第一个案例 四.简单流程及配置 五.使用注解开发Controller 六.参数绑定 ...

  3. SSM(spring mvc+spring+mybatis)学习路径——1-1、spring入门篇

    目录 1-1 Spring入门篇 专题一.IOC 接口及面向接口编程 什么是IOC Spring的Bean配置 Bean的初始化 Spring的常用注入方式 专题二.Bean Bean配置项 Bean ...

  4. SSM 三大框架系列:Spring 5 + Spring MVC 5 + MyBatis 3.5 整合(附源码)

    之前整理了一下新版本的 SSM 三大框架,这篇文章是关于它的整合过程和项目源码,版本号分别为:Spring 5.2.2.RELEASE.SpringMVC 5.2.2.RELEASE.MyBatis ...

  5. Spring、Spring MVC、MyBatis

    Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. Sp ...

  6. 转载 Spring、Spring MVC、MyBatis整合文件配置详解

    Spring.Spring MVC.MyBatis整合文件配置详解   使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. ...

  7. 搭建Spring、Spring MVC、Mybatis和Freemarker

    搭建Spring.Spring MVC.Mybatis和Freemarker 1.pom文件 <project xmlns="http://maven.apache.org/POM/4 ...

  8. IDEA下创建Maven项目,并整合使用Spring、Spring MVC、Mybatis框架

    项目创建 本项目使用的是IDEA 2016创建. 首先电脑安装Maven,接着打开IDEA新建一个project,选择Maven,选择图中所选项,下一步. 填写好GroupId和ArtifactId, ...

  9. spring MVC、mybatis配置读写分离

    spring MVC.mybatis配置读写分离 1.环境: 3台数据库机器,一个master,二台slave,分别为slave1,slave2 2.要实现的目标: ①使数据写入到master ②读数 ...

随机推荐

  1. 这里有最全的C/C++入门到进阶书籍推荐,你需要嘛?

    编程是操作性很强的一门知识,看书少不了,但只有学习和实践相结合才能起到很好的效果,一种学习方法是看视频->看书->研究书中例子->自己做些东西->交流->看书. 研究经典 ...

  2. 观察者模式-C#实现

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 观察者模式有四个角色:抽象主题.具体主题.抽象观察者.具体观察者. 抽象主题:把所有观察者对象 ...

  3. @RequestParam 和 @RequestBody 接受的时间格式

    这两个接受的时间格式不相同 首先看一下他们的区别 @RequestParam用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容.(Ht ...

  4. centos6.6安装redis

    .安装仓库 yum install epel-release -y2.安装redis yum install redis -y3.程序文件说明 安装完毕后有以下几个文件位于/usr/bin目录: re ...

  5. 题解报告:hdu 1279 验证角谷猜想

    Problem Description 数论中有许多猜想尚未解决,其中有一个被称为“角谷猜想”的问题,该问题在五.六十年代的美国多个著名高校中曾风行一时,这个问题是这样描述的:任何一个大于一的自然数, ...

  6. Java系列学习(零)-写在前面的话

    1.为什么写这套笔记 理由一:因为需求,所以学习,然后就要记笔记 理由二:同时学几种相似的语言,怕搞混,所以写 2.笔记修改日志

  7. python--11、数据库及SQL基础

    常用命令记录 查看库中所有表的引擎 SHOW TABLE STATUS FROM `center_main_db`; 还有一个更简洁,查询cmol_system_db库所有表的存储引擎\ SELECT ...

  8. 3分钟看懂flex布局

    首先要有个容器,并设置display:flex;display:-webkit-flex;该容器有以下六个属性: 1 2 3 4 5 6 7 8 9 10 11 12 flex-direction ( ...

  9. Spring的核心机制依赖注入

    原文地址:http://developer.51cto.com/art/200610/33311.htm 本文主要讲解依赖注入(设值注入.构造注入),作用是可以使Spring将各层的对象以松耦合的方式 ...

  10. Ruby开发环境的搭建

    1.Ruby的下载 https://rubyinstaller.org/downloads/ 2.Ruby的安装 3.Eclipse配置Ruby开发环境 插件地址:http://rubyeclipse ...