Spring事务管理

事务的特性:一致性、原子性、隔离性、持久性

Spring事务管理相关接口:PlatformTransactionManager(事务管理器)、TransactionDefinition(事务定义信息,隔离、传播、超时、只读)、TransactionStatus(事务具体运行状态)

1、事务管理器

相关的PlatformTransactionManager接口

Spring事务管理

2、事务隔离级别

当不考虑隔离性会引起一下问题:

(1)脏读:一个事务读取了另一个事务改写但未提交的数据,如果这些数据被回滚则读到的数据是无效的。A进行update、insert时候,B读取了中间状态不知道对不对的值。

(2)不可重复读:在同一事务中,多次读取同一数据返回的结果不同。B在A 的update操作前后,读到的数据不一致。

(3)幻读:一个事务读取了几行记录后,另一个事务插入一些记录,再后来查询中第一个事务就会发现有些原来没有的记录。B在A的insert操作前后,读到了的数据不一致。

事务的四种隔离级别,Mysql默认使用REPEATABLE_READ隔离级别,orcale默认使用READ_COMMOTTED

Spring事务管理

3、事务传播行为

事务传播行为:解决业务层方法之间的相互调用的问题

七种事务传播行为,其中分为三类。

第一类:PROPAGATION_REQUIRED(重点)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY

第二类:PROPAGATION_REQUIRES_NEW(重点)、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER

第三类:PROPAGATION_NESTED(重点)

Spring事务管理

4、Spring事务管理的实现方式

(1)编码式事务管理:

手动编写代码进行事务管理(很少使用)

(2)声明式事务管理:

基于TransactionProxyFactoryBean的方式(很少使用):需要为每一个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强。

基于AspectJ的XML方式(经常使用):一旦配置好后,类不需要加任何东西。

基于注解的方式(经常使用):配置简单,需要在业务层类上或方法上加上一个注解@Transactional。

1、 手动编写代码进行事务管理

applicationContext.xml文件。(主要transactionManager和transactionTemplate)

  <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="accountDao" class="cn.muke.spring.demo1.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    bean>

    <bean id="accountService" class="cn.muke.spring.demo1.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="transactionTemplate" ref="transactionTemplate" />
    bean>

    <bean id="transactionManager" 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="transactionManager"/>
    bean>

业务类

实现transactionTemplate的execute

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    private TransactionTemplate transactionTemplate;

    @Override
    public void transfer(final String out, final String in, Double money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                accountDao.outMoney(out, money);
                int i = 1/0;
                accountDao.inMoney(in, money);
            }
        });

    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }
}

2、基于TransactionProxyFactoryBean的方式

applicationContext.xml(需要为每个类配置TransactionProxyFactoryBean)

     <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="accountDao" class="cn.muke.spring.demo2.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    bean>

    <bean id="accountService" class="cn.muke.spring.demo2.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    bean>

    <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 key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticExceptionprop>
            props>
        property>
    bean>

业务层(不需做任何代码改动)

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    @Override
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out, money);
        int i = 1 / 0;
        accountDao.inMoney(in, money);
    }
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
}

3、基于AspectJ的XML方式

applicationContext.xml(txAdvice,切面编程)

     <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="accountDao" class="cn.muke.spring.demo3.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    bean>

    <bean id="accountService" class="cn.muke.spring.demo3.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>

            <tx:method name="transfer" propagation="REQUIRED" no-rollback-for="java.lang.ArithmeticException" />
        tx:attributes>
    tx:advice>

    <aop:config>

        <aop:pointcut expression="execution(* cn.muke.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
    aop:config>

业务层(不需做任何代码改动)

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    @Override
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out, money);
        int i = 1 / 0;
        accountDao.inMoney(in, money);
    }
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
}

4、基于注解的方式

applicationContext.xml(开启注解事务)

     <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="accountDao" class="cn.muke.spring.demo4.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    bean>

    <bean id="accountService" class="cn.muke.spring.demo4.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

业务层(增加注解@Transactional)

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    /**
     * propagation              :事务的传播行为
     * isolation                :事务的隔离级别
     * readOnly                 :只读
     * noRollbackFor            :发生哪些异常事务不回滚
     * noRollbackForClassName   :发生哪些异常事务不回滚
     * rollbackFor              :发生哪些异常回滚事务
     * rollbackForClassName     :发生哪些异常回滚事务
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out, money);
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            throw new RuntimeException();
        }
        accountDao.inMoney(in, money);
    }
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
}

项目代码在文件中

Original: https://www.cnblogs.com/maple92/p/8612938.html
Author: Topze
Title: Spring事务管理

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582950/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 巧妙绕过 “您的链接不是私密链接”

    大家上网的时候,有时候会碰到Chrome提示”您的链接不是私密链接”, 运气好的话,点击高级,有一个选项是”继续浏览不安全的网页”,…

    Linux 2023年6月13日
    0127
  • 数字证书工作原理 图文并茂

    SSL证书和HTTPS的关系 HTTPS在HTTP的基础上加入了SSL加密协议,HTTP是明文传输,HTTPS是加密传输。 A quick definition:HTTPS sta…

    Linux 2023年6月6日
    0115
  • 部署solr服务

    前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 一、S orl单机部署 准备:solr5.5、tomcat8.5、jdk1.8 2.复制./solr-5.5.0/s…

    Linux 2023年6月14日
    0118
  • IDEA快捷键总结

    一、关于IDEA工具的快捷键 1.1、字体设置  file –> settings –> 输入font –> 设置字体样式以及字号大小​1.1、快速生成ma…

    Linux 2023年6月7日
    086
  • RPA 微信财务报销机器人 竹间智能

    bash;gutter:true; 1、首先通过微信对话机器人收集报销信息及内容 2、上传发票并进行OCR识别 3、收集相关的出差信息,支持对话中修改内容 4、完成信息收集后,后台…

    Linux 2023年6月7日
    0100
  • jmeter&WebSocket直播间性能测试

    http://t.csdn.cn/GfXzJ 1.Jmeter本身是支持HTTP方法,要测试WebSocket的接口,首先要安装插件。 安装插件的方法:1)首先下载插件管理器① 访…

    Linux 2023年6月8日
    096
  • C语言课堂–现代编译环境搭建[2020年7月]

    看过了很多专家吐槽目前的大学c语言教学问题多多: 教材难懂,消磨了学生的兴趣; 环境老旧,都2020了还有在用VC6甚至TurboC 2.0,语法不规范。 轮到自己上课,心想可不能…

    Linux 2023年6月7日
    0108
  • 接口压测提示redis获取不到连接数,出现timeout waiting for idle object异常问题定位

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/qmfsun/p/11583355.htmlAuthor…

    Linux 2023年5月28日
    092
  • 玩转redis-延时消息队列

    上一篇基于 redis的list实现了一个简单的消息队列:玩转redis-简单消息队列 源码地址 使用demo 产品经理经常说的一句话,我们不光要有 X功能,还要 Y功能,这样客户…

    Linux 2023年5月28日
    0122
  • rsync

    rsync是什么 rsync特性 1)可以镜像保存整个目录树和文件系统。 2)可以很容易做到保持原来文件的权限、时间、软硬连接等。 3)无需特殊权限即可安装。 4)快速:第一次同步…

    Linux 2023年6月6日
    091
  • C++类结构体与json相互转换

    1. 背景与需求 之前写C#的时候,解析json字符串一般使用的是开源的类库Newtonsoft.Json,方法十分简洁,比如: class Project { public st…

    Linux 2023年6月8日
    0101
  • 记一次因网络变更导致zabbix连接es报400和404

    背景 zabbix历史数据存储到es集群,正常工作中的时候,因网络变更导致zabbix server连接不上es,zabbix日志首先报400错误,之后一直404,es那边报查询相…

    Linux 2023年6月7日
    0108
  • Gumbel_Softmax 概要

    解决argmax不可导,无法进行反向传播的问题 出现的原因: argmax(x,y)不可导的根本原因是其向量空间不是光滑的,有尖锐的点和面;而是某些任务中,argmax会被插入到反…

    Linux 2023年6月7日
    0111
  • DML

    用来对数据库中的表的数据进行增删改 添加数据 给指定列添加数据 insert into <表名> (&#x5217;&#x540D;1, &#x…

    Linux 2023年6月7日
    097
  • tcpreplay重放报文,tcpdump能抓到包,应用程序收不到包

    现象: 生产环境中有两台服务器A、B,A服务器实时有报文发往B服务器。为了在测试环境测试新功能,故在现网A服务器上tcpdump抓取发往B服务器的报文,然后在测试环境tcprewr…

    Linux 2023年6月14日
    0104
  • PTA 《基础编程题目集》 6-7 统计某类完全平方数

    本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144、676等。 函数接口定义: int IsTheNumber ( const i…

    Linux 2023年6月8日
    0116
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球