Mybatis深入之事务管理

article/2025/9/15 3:55:42

Mybatis之事务管理

简介

Mybatis的事务管理分为两种JdbcTransaction,ManagedTransaction。其中JdbcTransaction仅仅是对数据库连接Connection的一个包装、内部管理数据库事务还是调用Connection的提交、回滚等事务操作方法。ManagedTransaction更直接、什么也没有做。直接将事务交给外部容器管理。

Mybatis事务管理相关类结构图

类概览:
类概览

类UML图(典型的简单工厂模式来创建Transaction):
类UML图

  • Transaction 封装事务管理方法的接口
  • TransactionFactory 抽象事务工厂生产方法
  • JdbcTransactionFactory实现TransactionFactory、用于生产JdbcTransaction的工厂类
  • ManagedTransactionFactory实现TransactionFactory、用于生产ManagedTransaction的工厂类
  • JdbcTransaction实现Transaction、只是对事务进行了一层包装、实际调用数据库连接Connection的事务管理方法
  • ManagedTransaction 实现Transaction没有对数据库连接做任何事务处理、交由外部容器管理

源码事务

事务配置

Mybatis中关于事务的配置是通过<transaction type="xx"/>来指定的。配置如下:

    <environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments>
  • type为”JDBC”时、使用JdbcTransaction管理事务。
  • type为”managed”时、使用ManagedTransaction管理事务(也就是交由外部容器管理)

    Mybatis深入之初始化过程 中知道配置文件如何解析的、其中关于事务方面的解析:

  private void environmentsElement(XNode context) throws Exception {//只关注事务部分...TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));...}
  private TransactionFactory transactionManagerElement(XNode context) throws Exception {if (context != null) {String type = context.getStringAttribute("type");Properties props = context.getChildrenAsProperties();TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();factory.setProperties(props);return factory;}throw new BuilderException("Environment declaration requires a TransactionFactory.");}
    typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
  • 重点在于根据type类型判断实例化何种TransactionFactory
  • 前面已经知道Mybatis两种事务配置的方式、这里使用的jdbc类型的事务
  • 上一篇分析DataSource实例化过程中有一段是关于根据DataSource的type来获取何种Factory的、这里原理同样
  • 通过TypeAliasRegistry根据type=’JDBC’来获取TransactionFactory实现类JdbcTransactionFactory

关键在于JdbcTransactionFactory通过newInstance()使用无参构造函数时做了什么工作

public class JdbcTransactionFactory implements TransactionFactory {public void setProperties(Properties props) {}public Transaction newTransaction(Connection conn) {return new JdbcTransaction(conn);}public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {return new JdbcTransaction(ds, level, autoCommit);}
}
  • JdbcTransactionFactory默认无参构造方法被调用
  • setProperties没有做任何实质性处理
  • 对比ManagedTransactionFactory不再贴代码

下面就是获取具有事务特性的数据库连接了
JdbcTransaction:

  public Transaction newTransaction(Connection conn) {return new JdbcTransaction(conn);}

ManagedTransaction:

  public Transaction newTransaction(Connection conn) {return new ManagedTransaction(conn, closeConnection);}
  • 两者都是通过Connection来创建具体的实例

JdbcTransaction:

public class JdbcTransaction implements Transaction {private static final Log log = LogFactory.getLog(JdbcTransaction.class);protected Connection connection;protected DataSource dataSource;protected TransactionIsolationLevel level;protected boolean autoCommmit;public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {dataSource = ds;level = desiredLevel;autoCommmit = desiredAutoCommit;}public JdbcTransaction(Connection connection) {this.connection = connection;}public Connection getConnection() throws SQLException {if (connection == null) {openConnection();}return connection;}public void commit() throws SQLException {if (connection != null && !connection.getAutoCommit()) {if (log.isDebugEnabled()) {log.debug("Committing JDBC Connection [" + connection + "]");}connection.commit();}}public void rollback() throws SQLException {if (connection != null && !connection.getAutoCommit()) {if (log.isDebugEnabled()) {log.debug("Rolling back JDBC Connection [" + connection + "]");}connection.rollback();}}public void close() throws SQLException {if (connection != null) {resetAutoCommit();if (log.isDebugEnabled()) {log.debug("Closing JDBC Connection [" + connection + "]");}connection.close();}}protected void setDesiredAutoCommit(boolean desiredAutoCommit) {try {if (connection.getAutoCommit() != desiredAutoCommit) {if (log.isDebugEnabled()) {log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]");}connection.setAutoCommit(desiredAutoCommit);}} catch (SQLException e) {// Only a very poorly implemented driver would fail here,// and there's not much we can do about that.throw new TransactionException("Error configuring AutoCommit.  "+ "Your driver may not support getAutoCommit() or setAutoCommit(). "+ "Requested setting: " + desiredAutoCommit + ".  Cause: " + e, e);}}protected void resetAutoCommit() {try {if (!connection.getAutoCommit()) {// MyBatis does not call commit/rollback on a connection if just selects were performed.// Some databases start transactions with select statements// and they mandate a commit/rollback before closing the connection.// A workaround is setting the autocommit to true before closing the connection.// Sybase throws an exception here.if (log.isDebugEnabled()) {log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]");}connection.setAutoCommit(true);}} catch (SQLException e) {log.debug("Error resetting autocommit to true "+ "before closing the connection.  Cause: " + e);}}protected void openConnection() throws SQLException {if (log.isDebugEnabled()) {log.debug("Opening JDBC Connection");}connection = dataSource.getConnection();if (level != null) {connection.setTransactionIsolation(level.getLevel());}setDesiredAutoCommit(autoCommmit);}}
  • 从源码中可知、JdbcTransaction如何管理事务的、如前面所说调用DataSource事务操作方法。
  • 并且对select不进行事务控制
  • 当使用DataSource创建数据库连接时、数据库的事务隔离级别使用DataSource默认的事务隔离级别
  • 如需指定事务的隔离级别、必须手动创建JdbcTransaction(调用另一个构造函数)
  • 关于事务隔离级别会在补充中有

ManagedTransaction:

public class ManagedTransaction implements Transaction {private static final Log log = LogFactory.getLog(ManagedTransaction.class);private DataSource dataSource;private TransactionIsolationLevel level;private Connection connection;private boolean closeConnection;public ManagedTransaction(Connection connection, boolean closeConnection) {this.connection = connection;this.closeConnection = closeConnection;}public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) {this.dataSource = ds;this.level = level;this.closeConnection = closeConnection;}public Connection getConnection() throws SQLException {if (this.connection == null) {openConnection();}return this.connection;}public void commit() throws SQLException {// Does nothing}public void rollback() throws SQLException {// Does nothing}public void close() throws SQLException {if (this.closeConnection && this.connection != null) {if (log.isDebugEnabled()) {log.debug("Closing JDBC Connection [" + this.connection + "]");}this.connection.close();}}protected void openConnection() throws SQLException {if (log.isDebugEnabled()) {log.debug("Opening JDBC Connection");}this.connection = this.dataSource.getConnection();if (this.level != null) {this.connection.setTransactionIsolation(this.level.getLevel());}}}
  • 重点看一下commit() rollback()方法,没有方法体。验证前面其关于事务的管理方式

到这里事务暂时告一段落、一般在使用时会与spring结合、将数据库连接、事务管理都交由spring管理。

补充

数据库隔离级别:

先对不同隔离级别涉及到的名词解释:
•   脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.  
•   不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.  
•   幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几

具体的隔离级别定义:


READ UNCOMMITTED(读未提交数据)    允许事务读取未被其他事务提交的变更,脏读、不可重复读和幻读的问题都会出现  READ COMMITED(读已提交数据)   只允许事务读取已经被其他事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然会出现  REPEATABLE READ(可重复读)   确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读,但幻读的问题依然存在  SERIALIZABLE(串行化)   确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可以避免,但性能十分低  Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED   
Mysql 支持 4 中事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ  

更多内容:Mybatis 目录


http://chatgpt.dhexx.cn/article/YArEsFld.shtml

相关文章

事务-2 Spring与Mybatis事务实现原理

背景&#xff1a; 本文承接事务-1 事务隔离级别和Spring事务传播机制&#xff0c;是事务专题的第二篇&#xff1b;主题内容是Mybatis和Spring事务原理&#xff0c;结合源码和案例进行介绍。 本文主题内容为事务原理, 尤重Spring事务原理; 会结合源码讲解整体流程, 但不会拘限于…

什么是事务?Mysql事务怎么用?Mybatis怎么操作事务的?Spring呢?快进来看看

目录 一、计算机中的事务 1. 概念 2.事务的ACID特性 3.事务类型 1)手动事务 2)自动事务 4.为什么需要事务? 5.优点 二、MySQL事务 1.语法格式: 2.关闭自动提交&#xff0c;开启新事务 3.开启自动提交&#xff0c;关闭事务控制 三、Mybatis事务 Mybatis开关事务控…

SpringBoot Mybatis事物管理

本文主要讲述springboot提供的声明式的事务管理机制。 一、一些概念 声明式的事务管理是基于AOP的&#xff0c;在springboot中可以通过Transactional注解的方式获得支持&#xff0c;这种方式的优点是&#xff1a; 1&#xff09;非侵入式&#xff0c;业务逻辑不受事务管理代码…

spring boot配置mybatis和事务管理

spring boot配置mybatis和事务管理 一、spring boot与mybatis的配置 1.首先,spring boot 配置mybatis需要的全部依赖如下&#xff1a; <!-- Spring Boot 启动父依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>s…

《深入理解mybatis原理》 MyBatis事务管理机制

MyBatis作为Java语言的数据库框架&#xff0c;对数据库的事务管理是其非常重要的一个方面。本文将讲述MyBatis的事务管理的实现机制。首先介绍MyBatis的事务Transaction的接口设计以及其不同实现JdbcTransaction 和 ManagedTransaction&#xff1b;接着&#xff0c;从MyBatis的…

MyBatis事务管理

一、概述 事务管理对于企业应用来说是至关重要的&#xff0c;即使出现异常情况&#xff0c;它也可以保证数据的一致性。 Spring Framework对事务管理提供了一致的抽象&#xff0c;其特点如下&#xff1a; 为不同的事务API提供一致的编程模型&#xff0c;比如JTA(Java Transac…

深入浅出Mybatis系列(五)Mybatis事务篇

在学习Mysql事务开始,分为两步。一.先看下Mysql的事务级别都有什么,然后看Mysql的事务级别设置命令。及常见问题。二.JDK是如何处理数据库操作的呢? Mybatis是如何实现JDK定义的事务级别操作。 一.Mysql的事务级别及常见概念 MySQL事务隔离级别 事务隔离级别脏读不可重复读幻…

详解 MyBatis 事务管理,彻底颠覆你对事务的理解!

来源&#xff1a;https://my.oschina.net/zudajun/blog/666764 前言 说到数据库事务&#xff0c;人们脑海里自然不自然的就会浮现出事务的四大特性、四大隔离级别、七大传播特性。四大还好说&#xff0c;问题是七大传播特性是哪儿来的&#xff1f;是 Spring 在当前线程内&…

MyBatis的事务

Mybatis管理事务是分为两种方式: (1)使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交 (2)使用MANAGED的事务管理机制&#xff0c;这种机制mybatis自身不会去实现事务管理&#xff0c;而是让程序的容器&#xff08;JBOSS,WebLogic&#xff09;来实现对…

MyBatis--事务

事务是基于关系型数据库的企业应用的重要组成部分&#xff0c;用来确保应用程序数据的完整性和一致性。 事务就是一个系列(一组、几个)操作的集合单元&#xff0c;这些操作要么全部完成&#xff0c;要么全部失败&#xff0c;如果某一个操作失败&#xff0c;就算是已经成功执行…

ResNet网络结构解析

ResNet是识别、检测中常用的backbone&#xff0c;看检测相关论文的时候重点都在方法创新上&#xff0c;并没有特别在意网络结构&#xff0c;但是到自己跑实验改网络的时候就涉及到结构细节问题&#xff0c;于是详细的看了下ResNet网络结构。下图是ResNet的网络结构简图&#xf…

resnet网络结构图

很重要&#xff0c;单独放

ResNet网络结构,BN以及迁移学习详解

网络中的亮点&#xff1a; 1.超深的网络结构&#xff08;超过1000层&#xff09; 2.提出residual(残差)模块 3.使用Batch Normalization加速训练&#xff08;丢弃dropout&#xff09; 左边是将卷积层和池化层进行一个简单的堆叠所搭建的网络结构 20层的训练错误率大概在1%…

ResNet网络结构详解(Tensorflow2.6.0实现网络结构)

文章目录 1.ResNetX网络结构表&#xff08;1&#xff09;论文地址&#xff1a;&#xff08;2&#xff09;ResNet18网络结构&#xff1a;&#xff08;3&#xff09;ResNet34网络结构&#xff1a; 2.卷积神经网络的发展(1).卷积神经网络的发展&#xff1a;&#xff08;2&#xff…

ResNet网络结构详解,网络搭建,迁移学习

前言&#xff1a; 参考内容来自up&#xff1a;6.1 ResNet网络结构&#xff0c;BN以及迁移学习详解_哔哩哔哩_bilibili up的代码和ppt&#xff1a;https://github.com/WZMIAOMIAO/deep-learning-for-image-processing 一、简介 ResNet 网络是在 2015年 由微软实验室提出&#xf…

ResNet网络结构详解与模型的搭建

ResNET(Deep Residual Learning for Image Recognition ) ResNet网络是在2015年由微软实验室提出&#xff0c;斩获当年ImageNet竞赛中分类任务第一名&#xff0c;目标检测第一名。获得COCO数据集中目标检测第一名&#xff0c;图像分割第一名。下图是ResNet34层模型的结构简图。…

Resnet网络结构图和对应参数表的简单理解

Resnet Resnet即就是残差网络&#xff0c;本文主要是对于resnet给出的网络结构图进行简单解释。 网络结构图 以上就是34层网络的网络结构图。 以上是18层、34层、50层、101层以及152层网络所对应的残差块。 我刚开始在网上看到这两张图片的时候&#xff0c;感觉一点都不懂&a…

pytorch Resnet 网络结构

最近在学习廖老师的pytorch教程&#xff0c;学到Resnet 这部分着实的烧脑&#xff0c;这个模型都捣鼓了好长时间才弄懂&#xff0c;附上我学习过程中最为不解的网络的具体结构连接&#xff08;网上一直没有找到对应网络结构&#xff0c;对与一个自学的学渣般的我&#xff0c;很…

ResNet网络结构解析--Pytorch

ResNet101–DSSD/SSD &#xff08;1&#xff09;ResNet在Pytorch官方代码中有5种不同深度的结构&#xff0c;分别为18、34、50、101、152&#xff08;各网络深度指的是“需要通过训练更新参数“的层数&#xff0c;如卷积层&#xff0c;全连接层等&#xff09;&#xff0c;和论…

ResNet网络结构详解及代码复现

1. ResNet论文详解 1.1. Introduction 一般网络越深&#xff0c;特征就越丰富&#xff0c;模型效果也就越好。在深度重要的驱动下&#xff0c;出现了2个问题&#xff1a; 梯度消失和梯度爆炸&#xff1a; 梯度消失&#xff1a;误差梯度<1&#xff0c;当网络层数增多时&…