MyBatis的事务

article/2025/9/16 4:55:26

Mybatis管理事务是分为两种方式:

(1)使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交
(2)使用MANAGED的事务管理机制,这种机制mybatis自身不会去实现事务管理,而是让程序的容器(JBOSS,WebLogic)来实现对事务的管理
在Mybatis的配置文件中可以配置事务管理方式如下:
在这里插入图片描述

1. 事务的配置

我们在使用MyBatis时,一般会在MyBatisXML配置文件中定义类似如下的信息:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--映入外部文件定义的属性,供此配置文件使用--><properties resource="jdbc.properties"></properties><environments default="development"><!-- 连接环境信息,取一个任意唯一的名字 --><environment id="development"><!-- mybatis使用jdbc事务管理方式 --><transactionManager type="jdbc"/><!-- mybatis使用连接池方式来获取连接 --><dataSource type="pooled"><!-- 配置与数据库交互的4个必要属性 --><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!-- 加载映射文件--><mappers><mapper resource="com/mybatis/EmployeeMapper.xml"/></mappers>   
</configuration>

<environment>节点定义了连接某个数据库的信息,其子节点<transactionManager>的type 会决定我们用什么类型的事务管理机制。

2.事务工厂的创建

MyBatis事务的创建是交给TransactionFactory 事务工厂来创建的,如果我们将的type 配置为"JDBC",那么,在MyBatis初始化解析节点时,会根据type="JDBC"创建一个JdbcTransactionFactory工厂,其源码如下:

  /*** 解析<transactionManager>节点,创建对应的TransactionFactory* @param context* @return* @throws Exception*/
private TransactionFactory transactionManagerElement(XNode context) throws Exception {if (context != null) {String type = context.getStringAttribute("type");Properties props = context.getChildrenAsProperties();/*在Configuration初始化的时候,会通过以下语句,给JDBC和MANAGED对应的工厂类typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);下述的resolveClass(type).newInstance()会创建对应的工厂实例*/TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();factory.setProperties(props);return factory;}throw new BuilderException("Environment declaration requires a TransactionFactory.");
}

如上述代码所示,如果type = “JDBC”,则MyBatis会创建一个JdbcTransactionFactory.class 实例;如果type=“MANAGED”,则MyBatis会创建一个MangedTransactionFactory.class实例。

MyBatis对<transactionManager>节点的解析会生成 TransactionFactory实例;而对解析会生成datasouce实例(关于dataSource的解析和原理,读者可以参照我的另一篇博文:《Mybatis数据源与连接池》)
作为<environment>节点,会根据TransactionFactory和DataSource实例创建一个Environment对象,代码如下所示:

private void environmentsElement(XNode context) throws Exception {if (context != null) {if (environment == null) {environment = context.getStringAttribute("default");}for (XNode child : context.getChildren()) {String id = child.getStringAttribute("id");//是和默认的环境相同时,解析之if (isSpecifiedEnvironment(id)) {//1.解析<transactionManager>节点,决定创建什么类型的TransactionFactoryTransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));//2. 创建dataSourceDataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));DataSource dataSource = dsFactory.getDataSource();//3. 使用了Environment内置的构造器Builder,传递id 事务工厂TransactionFactory和数据源DataSourceEnvironment.Builder environmentBuilder = new Environment.Builder(id).transactionFactory(txFactory).dataSource(dataSource);configuration.setEnvironment(environmentBuilder.build());}}}
}

Environment表示着一个数据库的连接,生成后的Environment对象会被设置到Configuration实例中,以供后续的使用。

3. 事务工厂TransactionFactory

事务工厂Transaction定义了创建Transaction的两个方法:

  • 通过指定的Connection对象创建Transaction
  • 通过数据源DataSource来创建Transaction

4. 事务Transaction的创建

通过事务工厂TransactionFactory很容易获取到Transaction对象实例。我们以JdbcTransaction为例,看一下JdbcTransactionFactory是怎样生成JdbcTransaction的,代码如下:

public class JdbcTransactionFactory implements TransactionFactory {public void setProperties(Properties props) {}/*** 根据给定的数据库连接Connection创建Transaction* @param conn Existing database connection* @return*/public Transaction newTransaction(Connection conn) {return new JdbcTransaction(conn);}/*** 根据DataSource、隔离级别和是否自动提交创建Transacion** @param ds* @param level Desired isolation level* @param autoCommit Desired autocommit* @return*/public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {return new JdbcTransaction(ds, level, autoCommit);}
}

如上说是,JdbcTransactionFactory会创建JDBC类型的Transaction,即JdbcTransaction。类似地,ManagedTransactionFactory也会创建ManagedTransaction。下面我们会分别深入JdbcTranaction 和ManagedTransaction,看它们到底是怎样实现事务管理的。

5. JdbcTransaction

JdbcTransaction直接使用JDBC的提交和回滚事务管理机制 。它依赖与从dataSource中取得的连接connection 来管理transaction 的作用域,connection对象的获取被延迟到调用getConnection()方法。如果autocommit设置为on,开启状态的话,它会忽略commit和rollback。

直观地讲,就是JdbcTransaction是使用的java.sql.Connection 上的commit和rollback功能,JdbcTransaction只是相当于对java.sql.Connection事务处理进行了一次包装(wrapper),Transaction的事务管理都是通过java.sql.Connection实现的。JdbcTransaction的代码实现如下:
/*** @see JdbcTransactionFactory*/
/*** @author Clinton Begin*/
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;}/*** commit()功能 使用connection的commit()* @throws SQLException*/public void commit() throws SQLException {if (connection != null && !connection.getAutoCommit()) {if (log.isDebugEnabled()) {log.debug("Committing JDBC Connection [" + connection + "]");}connection.commit();}}/*** rollback()功能 使用connection的rollback()* @throws SQLException*/public void rollback() throws SQLException {if (connection != null && !connection.getAutoCommit()) {if (log.isDebugEnabled()) {log.debug("Rolling back JDBC Connection [" + connection + "]");}connection.rollback();}}/*** close()功能 使用connection的close()* @throws SQLException*/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);}}

6. ManagedTransaction

ManagedTransaction让容器来管理事务Transaction的整个生命周期,意思就是说,使用ManagedTransaction的commit和rollback功能不会对事务有任何的影响,它什么都不会做,它将事务管理的权利移交给了容器来实现。看如下Managed的实现代码大家就会一目了然:

/**** 让容器管理事务transaction的整个生命周期* connection的获取延迟到getConnection()方法的调用* 忽略所有的commit和rollback操作* 默认情况下,可以关闭一个连接connection,也可以配置它不可以关闭一个连接* 让容器来管理transaction的整个生命周期* @see ManagedTransactionFactory*/
/*** @author Clinton Begin*/
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());}}}

注意:如果我们使用MyBatis构建本地程序,即不是WEB程序,若将type设置成"MANAGED",那么,我们执行的任何update操作,即使我们最后执行了commit操作,数据也不会保留,不会对数据库造成任何影响。因为我们将MyBatis配置成了“MANAGED”,即MyBatis自己不管理事务,而我们又是运行的本地程序,没有事务管理功能,所以对数据库的update操作都是无效的。


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

相关文章

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;当网络层数增多时&…

resnet50网络结构_pytorch实践(改造属于自己的resnet网络结构并训练二分类网络)

我的CSDN博客:https://blog.csdn.net/litt1e 我的公众号:工科宅生活 在学习pytorch过程中,突然想拥有属于自己的网络结构,于是便自己选择了一个比较简单的resnet18进行改造,并用其对蚂蚁和蜜蜂进行分类,比较一下没有经过预训练的resnet18好还是自己改造的resnet_diy好。 …

【DL系列】ResNet网络结构详解、完整代码实现

Name&#xff1a; Deep Residual Learning for Image Recognition Author&#xff1a; 何恺明团队 Publiced&#xff1a; 2015.12_CVPR 文章目录 前言1. 残差网络待解决的问题2. ResNet模型亮点 ResNet模型结构1. 残差学习2. Residual模块3. ResNet模型 ResNet-layers模型完整代…

pytorch实现resnet网络结构

ResNet结构和pytorch实现 resnet的网络结构都是经过5个不同数量的残差块最后一个全连接分类完成的。 在resnet50以后&#xff0c;由于层数的增加残差块发生了变化&#xff0c;从原来3x3卷积变为三层卷积&#xff0c;卷积核分别为1x1、3x3、1x1&#xff0c;减少了网络参数。主…

ResNet网络结构搭建

ResNet 下图为包含有18层(17个卷积层和1个全连接层)、34层(33个卷积层和1个全连接层)、50层(49个卷积层和1个全连接层)、101层(100个卷积层和1个全连接层)、152层(151个卷积层和1个全连接层)的resnet结构 下图是论文中给出的两种残差结构。左边的残差结构是针对层数较少网络&a…

ResNet网络结构

注&#xff1a;深度好像就是channel w*h*c 根据b站up霹雳吧啦的讲解做的笔记 视频地址6.1 ResNet网络结构&#xff0c;BN以及迁移学习详解_哔哩哔哩_bilibiliR 6.2 使用pytorch搭建ResNet并基于迁移学习训练_哔哩哔哩_bilibili ResNet网络解决梯度消失、爆炸&#xff0c;以及…

经典网络ResNet介绍

经典网络ResNet(Residual Networks)由Kaiming He等人于2015年提出&#xff0c;论文名为《Deep Residual Learning for Image Recognition》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/1512.03385.pdf ResNet要解决的是深度神经网络的”退化(degradation)”问题&…

六、ResNet网络详细解析(超详细哦)

1、 RestNet网络 1.1、 RestNet网络结构 ResNet在2015年被提出&#xff0c;在ImageNet比赛classification任务上获得第一名&#xff0c;因为它“简单与实用”并存&#xff0c;之后很多方法都建立在ResNet50或者ResNet101的基础上完成的&#xff0c;检测&#xff0c;分割&…

ResNet结构

文章目录 系列文章目录一、Residual net(残差网络)二、BatchNormalization(BN)三、ResNet结构 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开…

深度学习之图像分类(七)--ResNet网络结构

深度学习之图像分类&#xff08;七&#xff09;ResNet 网络结构 目录 深度学习之图像分类&#xff08;七&#xff09;ResNet 网络结构1. 前言2. Residual3. 网络配置4. 代码 本节学习ResNet网络结构&#xff0c;以及迁移学习入门&#xff0c;学习视频源于 Bilibili&#xff0c;…