广告
返回顶部
首页 > 资讯 > 后端开发 > Python >一文搞懂 MyBatis的事务管理机制
  • 704
分享到

一文搞懂 MyBatis的事务管理机制

MyBatis事务管理机制MyBatis事务管理MyBatis事务 2023-05-20 05:05:27 704人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录一、事务概述二、mybatis 实现事务的方式1. 编程式事务2. 声明式事务(1)JDBC 事务管理器(2)spring 事务管理器三、事务源码理解(1)Transaction

一、事务概述

事务是指要么全部执行成功,要么全部回滚的一组操作。在数据库中,一般使用 ACID 规则来约束事务,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。在 MyBatis 中,也遵循了这一规则。

MyBatis中的事务是指一系列数据库操作,这些操作要么全部执行成功,要么全部执行失败。如果操作过程中发生错误,所有对数据库的修改都将被回滚,即还原到最初状态。事务是确保数据一致性和完整性的关键机制之一。

在MyBatis中,我们可以通过三种方式来管理事务:

  • 编程式管理事务:在代码中显式开启、提交或回滚事务。

  • 声明式管理事务:通过aop代理实现事务管理,可以让代码更简洁,更容易维护。

  • 注解式管理事务:通过注解方式管理事务,是声明式管理事务的一种扩展方式。

以上三种方式,最常用的是声明式管理事务,它可以将事务管理和业务逻辑分离,降低代码的耦合度,提高代码的可读性和可维护性。在MyBatis中,声明式事务管理需要借助Spring框架来实现。

在使用声明式事务管理时,我们需要在Spring配置文件中配置TransactionManager和TransactionProxyFactoryBean两个bean,其中TransactionManager负责事务管理,TransactionProxyFactoryBean负责AOP代理。

下面是一个示例:

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

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.example.UserMapper"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

<bean id="userMapperProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager" />
    <property name="target" ref="userMapper" />
    <property name="transactionAttributes">
        <props>
            <prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="insert*">PROPAGATION_REQUIRED</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

在编写完上述配置后,我们就可以对UserMapper接口中的方法进行事务管理了。例如,在UserService类中,我们可以注入userMapperProxy,并调用其中的方法:

@Service
public class UserService {

    @Autowired
    UserMapper userMapperProxy;

    @Transactional
    public void addUser(User user) {
        userMapperProxy.addUser(user);
    }
}

在代码中,通过@Transactional注解声明了该方法需要进行事务管理,当方法执行过程中发生异常时,事务将会回滚。

MyBatis支持多种事务管理方式,但是建议使用声明式事务管理,因为它能够最大程度地降低代码的耦合度,并提高代码的可读性和可维护性。

二、MyBatis 实现事务的方式

MyBatis 实现事务也有多种方式,其中最常用的方式有两种:编程式事务和声明式事务。接下来我们将分别来介绍这两种方式。

1. 编程式事务

编程式事务就是通过编写代码来手动管理事务,主要包括以下几个步骤:

1)获取 SqlSession 对象;

2)设置自动提交为 false;

3)执行数据库操作;

4)提交事务;

5)关闭 SqlSession。

代码示例如下:

SqlSession sqlSession = sqlSessionFactory.openSession(false);
try {
    // 执行数据库操作
    sqlSession.insert("insertUser", user);
    sqlSession.update("updateUser", user);
    
    // 提交事务
    sqlSession.commit();
} catch (Exception e) {
    // 回滚事务
    sqlSession.rollback();
} finally {
    // 关闭 SqlSession
    sqlSession.close();
}

以上代码中,通过设置自动提交为 false 来关闭自动提交事务的方式,然后在 try 块中执行需要进行事务管理的数据库操作,如果出现异常则回滚事务,否则提交事务,并在 finally 中关闭 SqlSession。

2. 声明式事务

声明式事务就是在配置文件中通过事务管理器来管理事务,这种方式更加灵活和方便,我们只需要在配置文件中配置好即可。MyBatis 内置了两个事务管理器:JDBC 和 Spring。

(1)JDBC 事务管理器

JDBC 事务管理器是 MyBatis 内置的一个事务管理器,在 SqlSessionFactory 的配置文件中进行配置:

<transactionManager type="JDBC" />

(2)Spring 事务管理器

Spring 事务管理器是基于 Spring 框架的事务管理器,需要引入 Spring 的包,并在 MyBatis 的配置文件中配置:

<transactionManager type="SPRING" />

在使用 Spring 事务管理器时,还需要在 Spring 的配置文件中配置事务管理器和数据源,具体可以参考 Spring 的文档。

三、事务源码理解

(1)TransactionFactory

在 MyBatis 中,事务工厂需要实现 org.apache.ibatis.transaction.TransactionFactory 接口,该接口有一个方法:

Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);

该方法用于创建一个新的 Transaction 实例。

例如,如果你要使用 JDBC 来管理事务,可以使用默认提供的 JdbcTransactionFactory 类来创建事务工厂。以下是一个创建事务工厂的示例代码:

import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import javax.sql.DataSource;

public class MyTransactionFactory {
    public static TransactionFactory createTransactionFactory() {
        return new JdbcTransactionFactory();
    }
}

以上代码中,我们使用 JdbcTransactionFactory 创建一个新的事务工厂。实际上,在 MyBatis 的配置文件中,可以直接引用这个工厂。

例如:

<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <!-- 数据源配置 -->
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="passWord" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <!-- Mapper 配置 -->
</configuration>

以上代码中,我们使用了 <transactionManager type="JDBC"/> 来配置事务管理器的类型,并且在 <dataSource> 标签中指定了数据源的类型为 POOLED,也就是一个连接池数据源。

在实际应用中,还可以通过自定义事务工厂来创建其他类型的事务。例如,如果你要使用 Atomikos 来管理事务,可以自定义一个 AtomikosTransactionFactory 类来创建事务工厂。

(2)JdbcTransaction

在 MyBatis 中,Transaction 接口的默认实现是 JdbcTransaction 类。这个类的创建是在 JdbcTransactionFactory 工厂类中完成的。

以下是 JdbcTransactionFactory 工厂类中用于创建 Transaction 实例的代码:

@Override
public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
  return new JdbcTransaction(dataSource, level, autoCommit);
}

在这段代码中,我们可以看到工厂方法 newTransaction() 的实现。该方法接收三个参数:数据源、事务隔离级别和是否自动提交。

newTransaction 方法中,我们使用这些参数创建一个新的 JdbcTransaction 实例,并将其返回。JdbcTransaction 类中实现了 Transaction 接口,因此可以直接返回。

以下是 JdbcTransaction 类的主要源码:

public class JdbcTransaction implements Transaction {

  protected Connection connection;
  protected DataSource dataSource;
  protected TransactionIsolationLevel level;
  protected boolean autoCommit;

  public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) throws SQLException {
    dataSource = ds;
    level = desiredLevel;
    autoCommit = desiredAutoCommit;
    openConnection();
    setDesiredAutoCommit();
    setDesiredTransactionIsolation();
  }

  // ...其他方法

}

JdbcTransaction 类中,我们创建了一个基本的事务对象,它包含了一些属性,例如事务管理器、连接、事务隔离级别等等。在构造函数中,我们使用传入的参数来初始化这些属性值。

除了构造函数之外,还有一些其他的方法用于对事务进行操作,例如提交、回滚、关闭等。这些方法都是从 Transaction 接口中继承来的。

因此,在 MyBatis 中,创建一个新的事务就是通过事务工厂和相应的创建方法来创建一个特定类型的事务对象。而在事务对象中,我们可以对事务进行各种操作。

(3)ManagedTransaction

在 MyBatis 中,除了 JdbcTransaction 之外,还提供了另外一种称为 ManagedTransaction 的事务实现,它是一种由容器或框架来管理的事务,而不是 MyBatis 内部来管理。

ManagedTransaction 接口的默认实现是 SpringManagedTransaction 类。该类实现了 MyBatis 的 Transaction 接口,但其本身并不处理任何事务逻辑,而是委托给 Spring 框架进行处理。

以下是 SpringManagedTransaction 类的主要源码:

public class SpringManagedTransaction implements Transaction {

  private final DataSource dataSource;
  private Connection connection;
  private boolean isConnectionTransactional;
  private boolean autoCommit;

  public SpringManagedTransaction(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  @Override
  public Connection getConnection() throws SQLException {
    if (this.connection == null) {
      openConnection();
    }
    return this.connection;
  }

  // ...其他方法

}

SpringManagedTransaction 类中,我们使用传入的数据源来创建一个新的事务对象。在 getConnection() 方法中,如果当前连接不存在,则会打开一个新的连接并返回;否则直接返回已经存在的连接。

需要注意的是,SpringManagedTransaction 并不自行管理事务,而是将事务管理工作交给了 Spring 框架。因此,如果要使用 SpringManagedTransaction,我们需要在 Spring 配置文件中配置相应的事务管理器,例如 DataSourceTransactionManagerJpaTransactionManager 等。

总之,相比于 JdbcTransactionManagedTransaction 更适合在容器或框架中使用,而不是在 MyBatis 内部使用。如果你使用 Spring 或其他类似的框架来管理事务,则可以考虑使用 ManagedTransaction 来实现 MyBatis 的事务管理。

四、测试用例

接下来我们将通过一个示例来详细介绍 MyBatis 的事务管理机制。假设我们需要执行一个复杂的业务操作,需要同时更新多个表,我们就可以使用编程式事务来管理事务。

在 Mapper.xml 文件中,编写如下 SQL 语句:

<insert id="insertUser" parameterType="com.example.User">
    insert into user (id, name, age) values (#{id}, #{name}, #{age})
</insert>

<update id="updateAccount" parameterType="com.example.Account">
    update account set balance = #{balance} where id = #{id}
</update>

然后我们编写一个 Service 类来调用 Mapper 文件中的方法,代码如下:

public class UserService {
    private SqlSessionFactory sqlSessionFactory;

    public UserService(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public void addUserAndAccount(User user, Account account) {
        SqlSession sqlSession = sqlSessionFactory.openSession(false);
        try {
            // 执行数据库操作
            sqlSession.insert("insertUser", user);
            sqlSession.update("updateAccount", account);
            
            // 提交事务
            sqlSession.commit();
        } catch (Exception e) {
            // 回滚事务
            sqlSession.rollback();
        } finally {
            // 关闭 SqlSession
            sqlSession.close();
        }
    }
}

以上代码中,我们通过 openSession(false) 来获取 SqlSession 对象,并设置自动提交为 false,然后在 try 块中执行数据库操作,如果出现异常则回滚事务,否则提交事务,并在 finally 中关闭 SqlSession。在实际开发中,我们可以将 SqlSession 放入 Spring 管理中,这样就更加方便了。

以上就是一文搞懂 MyBatis的事务管理机制的详细内容,更多关于MyBatis 事务管理的资料请关注编程网其它相关文章!

--结束END--

本文标题: 一文搞懂 MyBatis的事务管理机制

本文链接: https://www.lsjlt.com/news/213903.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一文搞懂 MyBatis的事务管理机制
    目录一、事务概述二、MyBatis 实现事务的方式1. 编程式事务2. 声明式事务(1)JDBC 事务管理器(2)Spring 事务管理器三、事务源码理解(1)Transaction...
    99+
    2023-05-20
    MyBatis事务管理机制 MyBatis事务管理 MyBatis事务
  • 一文搞懂MySQL运行机制原理
    目录前言mysql服务器体系架构网络连接层服务层存储引擎层系统文件层服务器处理客户端请求连接管理解析与优化查询缓存语法解析查询优化存储引擎小结前言 前文我们了解了MySQL采用客户端/服务器架构,用户通过客户端程序发送增...
    99+
    2022-09-30
  • 一文搞懂JavaSPI机制的原理与使用
    目录SPI 概念举个栗子第一步第二步第三步第四步原理常用的框架优缺点优点缺点Java 程序员在日常工作中经常会听到 SPI,而且很多框架都使用了 SPI...
    99+
    2022-11-13
  • 一文搞懂Spring Security异常处理机制
    目录1.异常分类2.ExceptionTranslationFilter3.自定义处理今天来和小伙伴们聊一聊 Spring Security 中的异常处理机制。 在 Spring S...
    99+
    2022-11-13
  • 一文搞懂Java的SPI机制(推荐)
    目录1 简介缺点 源码使用适用场景插件扩展案例1 简介 SPI,Service Provider Interface,一种服务发现机制。 有了SPI,即可实现服务接口与服务实现的解...
    99+
    2022-11-12
  • 一文搞懂Java中的反射机制
    目录一. 反射的概念二. 为什么需要反射三. 反射的基石四. 反射的实现1. 获取字节码文件对象 2. 反射的使用 反射的优缺点 一. 反射的概念 Ja...
    99+
    2022-11-13
  • 一文搞懂Python的函数传参机制
    目录一、最简单的函数(无返回值、参数)二、最简单的函数(带返回值、无参数)三、带一个参数(无默认值)四、带有多个参数(无默认值)五、参数设置默认值(一个参数)六、参数设置默认值(多个...
    99+
    2022-11-11
  • 一文快速搞懂MySQL InnoDB事务ACID实现原理
    【51CTO.com原创稿件】说到数据库事务,想到的就是要么都做修改,要么都不做,或者是 ACID 的概念。其实事务的本质就是锁、并发和重做日志的结合体。 这一篇主要讲一下 InnoDB 中的事务到底是如何...
    99+
    2022-10-18
  • 一文带你读懂SpringBoot中的事务管理
    一文带你读懂SpringBoot中的事务管理?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Springboot内部提供的事务管理器是根据autoconfigur...
    99+
    2023-05-31
    springboot bo 事务管理
  • 【Redis进阶】一文搞懂Redisson的看门狗机制底层实现
    文章目录 1. 看门狗机制概述2. 源码解读3. 总结 1. 看门狗机制概述 看门狗机制是Redission提供的一种自动延期机制,这个机制使得Redission提供的分布式锁是可以自动续...
    99+
    2023-09-01
    redis java 数据库
  • 如何理解Spring的Hibernate事务管理机制
    如何理解Spring的Hibernate事务管理机制,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。主要讲了Spring 声明式事务让我们从复杂的Hibernate事务处理中...
    99+
    2023-06-17
  • 一文解析spring中事务的传播机制
    今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。Spring中的事务Spring的事务其实就是数据库的事务操作,符合ACID标...
    99+
    2023-07-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作