最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis事務(wù)原理與實(shí)戰(zhàn)深入解析

 更新時(shí)間:2025年12月26日 09:41:07   作者:故淵ZY  
本文詳細(xì)解析了MyBatis事務(wù)的原理、配置與企業(yè)級(jí)實(shí)戰(zhàn)應(yīng)用,從核心基礎(chǔ)到原生JDBC事務(wù)和Spring聲明式事務(wù)的實(shí)現(xiàn),再到常見問(wèn)題與解決方案,全面涵蓋了MyBatis事務(wù)的各個(gè)方面,幫助開發(fā)者深入理解并正確使用MyBatis事務(wù),感興趣的朋友跟隨小編一起看看吧

MyBatis 事務(wù)深度解析:原理、配置與企業(yè)級(jí)實(shí)戰(zhàn)

事務(wù)是保證數(shù)據(jù)一致性的核心機(jī)制,尤其在多步數(shù)據(jù)庫(kù)操作場(chǎng)景中(如 “下單減庫(kù)存”“轉(zhuǎn)賬轉(zhuǎn)賬”),事務(wù)的 ACID 特性(原子性、一致性、隔離性、持久性)能避免出現(xiàn)數(shù)據(jù)臟讀、幻讀、部分成功等問(wèn)題。MyBatis 作為持久層框架,本身不直接管理事務(wù),而是依賴底層數(shù)據(jù)源(如 JDBC)或整合 Spring 框架實(shí)現(xiàn)事務(wù)控制。本文將從事務(wù)核心概念出發(fā),深入拆解 MyBatis 事務(wù)的實(shí)現(xiàn)原理、兩種核心使用方式(原生 JDBC 事務(wù)、Spring 聲明式事務(wù))、隔離級(jí)別配置及企業(yè)級(jí)實(shí)戰(zhàn)場(chǎng)景,幫助開發(fā)者徹底掌握 MyBatis 事務(wù)的正確用法。

一、核心基礎(chǔ):MyBatis 事務(wù)的本質(zhì)與依賴

1. 事務(wù)的核心價(jià)值

在無(wú)事務(wù)控制的場(chǎng)景中,多步數(shù)據(jù)庫(kù)操作可能出現(xiàn) “部分成功” 的風(fēng)險(xiǎn)。例如 “用戶下單” 流程需執(zhí)行兩步操作:① 插入訂單記錄;② 扣減商品庫(kù)存。若第一步成功、第二步失敗,會(huì)導(dǎo)致 “訂單已創(chuàng)建但庫(kù)存未扣減” 的臟數(shù)據(jù)。事務(wù)的核心價(jià)值就是通過(guò) ACID 特性保證:多步操作 “要么全成功,要么全回滾”,確保數(shù)據(jù)一致性。

2. MyBatis 事務(wù)的底層依賴

MyBatis 本身不提供事務(wù)管理器,事務(wù)控制依賴以下兩種底層機(jī)制,核心是通過(guò)SqlSession控制數(shù)據(jù)庫(kù)連接的事務(wù)行為:

  • JDBC 事務(wù):依賴 JDBC 的Connection對(duì)象,通過(guò)setAutoCommit(false)關(guān)閉自動(dòng)提交,commit()提交事務(wù),rollback()回滾事務(wù),適用于非 Spring 環(huán)境;
  • Spring 事務(wù):Spring 提供統(tǒng)一的事務(wù)管理器(DataSourceTransactionManager),MyBatis 通過(guò)SqlSessionFactory與 Spring 事務(wù)管理器整合,支持聲明式事務(wù)(@Transactional注解),是企業(yè)級(jí)開發(fā)的主流方案。

3. MyBatis 事務(wù)的核心組件

  • SqlSession:MyBatis 的核心會(huì)話對(duì)象,每個(gè) SqlSession 綁定一個(gè)數(shù)據(jù)庫(kù)連接(Connection),事務(wù)的提交 / 回滾本質(zhì)是通過(guò) SqlSession 控制 Connection 的事務(wù)行為;
  • TransactionFactory:事務(wù)工廠,負(fù)責(zé)創(chuàng)建Transaction對(duì)象,默認(rèn)提供JdbcTransactionFactory(適配 JDBC 事務(wù))和ManagedTransactionFactory(適配容器管理事務(wù));
  • Transaction:事務(wù)接口,封裝了事務(wù)的提交、回滾、關(guān)閉等操作,底層委托給 Connection 實(shí)現(xiàn);
  • Executor:MyBatis 的執(zhí)行器,所有數(shù)據(jù)庫(kù)操作通過(guò) Executor 執(zhí)行,Executor 會(huì)通過(guò) Transaction 獲取數(shù)據(jù)庫(kù)連接,確保同一事務(wù)內(nèi)的操作使用同一個(gè) Connection。

二、原生 JDBC 事務(wù):MyBatis 手動(dòng)控制事務(wù)(非 Spring 環(huán)境)

在不使用 Spring 框架的場(chǎng)景中,MyBatis 通過(guò)原生 JDBC 事務(wù)實(shí)現(xiàn)手動(dòng)控制,核心是通過(guò)SqlSessioncommit()rollback()方法管理事務(wù),底層依賴 JDBC 的 Connection 對(duì)象。

1. 核心原理

  • MyBatis 默認(rèn)開啟 “自動(dòng)提交事務(wù)”(autoCommit=true),即每個(gè) SQL 語(yǔ)句獨(dú)立成為一個(gè)事務(wù),執(zhí)行后自動(dòng)提交;
  • 手動(dòng)控制事務(wù)時(shí),需先通過(guò)sqlSessionFactory.openSession(false)關(guān)閉自動(dòng)提交,此時(shí) SqlSession 綁定的 Connection 處于 “事務(wù)未提交” 狀態(tài);
  • 多步 SQL 操作執(zhí)行完成后,調(diào)用sqlSession.commit()提交事務(wù);若執(zhí)行過(guò)程中拋出異常,調(diào)用sqlSession.rollback()回滾事務(wù);
  • 事務(wù)提交 / 回滾后,需關(guān)閉 SqlSession 釋放連接。

2. 實(shí)戰(zhàn)演示:原生 JDBC 事務(wù)手動(dòng)控制

(1)環(huán)境準(zhǔn)備(非 Spring)
  • 依賴配置(pom.xml):
<!-- MyBatis核心依賴 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.13</version>
</dependency>
<!-- MySQL驅(qū)動(dòng) -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>
<!-- 數(shù)據(jù)源(C3P0) -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>
  • MyBatis 配置文件(mybatis-config.xml):
<configuration>
    <!-- 環(huán)境配置:配置事務(wù)工廠和數(shù)據(jù)源 -->
    <environments default="development">
        <environment id="development">
            <!-- 事務(wù)工廠:使用JDBC事務(wù)工廠 -->
            <transactionManager type="JDBC"/>
            <!-- 數(shù)據(jù)源:C3P0連接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis?useSSL=false&serverTimezone=Asia/Shanghai"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
                <property name="poolMaximumActiveConnections" value="10"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 映射器掃描 -->
    <mappers>
        <mapper resource="mapper/OrderMapper.xml"/>
        <mapper resource="mapper/ProductMapper.xml"/>
    </mappers>
</configuration>
(2)Mapper 接口與 XML(下單減庫(kù)存場(chǎng)景)
  • OrderMapper.java(插入訂單):
public interface OrderMapper {
    int insertOrder(Order order);
}
  • ProductMapper.java(扣減庫(kù)存):
public interface ProductMapper {
    int decreaseStock(@Param("productId") Long productId, @Param("num") Integer num);
}
  • OrderMapper.xml:
<mapper namespace="com.example.mapper.OrderMapper">
    <insert id="insertOrder" parameterType="com.example.entity.Order">
        INSERT INTO `order`(order_no, product_id, num, create_time)
        VALUES(#{orderNo}, #{productId}, #{num}, NOW())
    </insert>
</mapper>
  • ProductMapper.xml:
<mapper namespace="com.example.mapper.ProductMapper">
    <update id="decreaseStock">
        UPDATE product SET stock = stock - #{num} WHERE id = #{productId} AND stock >= #{num}
    </update>
</mapper>
(3)手動(dòng)控制事務(wù)代碼
public class TransactionDemo {
    public static void main(String[] args) {
        // 1. 加載MyBatis配置,創(chuàng)建SqlSessionFactory
        String resource = "mybatis-config.xml";
        try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            // 2. 開啟SqlSession,關(guān)閉自動(dòng)提交(false表示手動(dòng)控制事務(wù))
            SqlSession sqlSession = sqlSessionFactory.openSession(false);
            try {
                // 3. 獲取Mapper接口
                OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
                ProductMapper productMapper = sqlSession.getMapper(ProductMapper.class);
                // 4. 模擬下單流程:① 插入訂單;② 扣減庫(kù)存
                Order order = new Order();
                order.setOrderNo(UUID.randomUUID().toString());
                order.setProductId(1L);
                order.setNum(2);
                orderMapper.insertOrder(order); // 第一步:插入訂單
                int rows = productMapper.decreaseStock(1L, 2); // 第二步:扣減庫(kù)存
                if (rows == 0) {
                    throw new RuntimeException("庫(kù)存不足,扣減失敗");
                }
                // 5. 所有操作成功,提交事務(wù)
                sqlSession.commit();
                System.out.println("事務(wù)提交成功:下單流程完成");
            } catch (Exception e) {
                // 6. 發(fā)生異常,回滾事務(wù)
                sqlSession.rollback();
                System.out.println("事務(wù)回滾:" + e.getMessage());
            } finally {
                // 7. 關(guān)閉SqlSession,釋放連接
                sqlSession.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 核心注意事項(xiàng)

  • 必須通過(guò)openSession(false)關(guān)閉自動(dòng)提交,否則事務(wù)控制失效;
  • 同一事務(wù)內(nèi)的所有操作必須使用同一個(gè) SqlSession(確保使用同一個(gè)數(shù)據(jù)庫(kù)連接);
  • 異常捕獲后必須手動(dòng)調(diào)用rollback(),否則事務(wù)會(huì)一直處于未提交狀態(tài),導(dǎo)致連接泄露;
  • 事務(wù)提交 / 回滾后,SqlSession 不可重復(fù)使用,需重新創(chuàng)建。

三、Spring 聲明式事務(wù):MyBatis 企業(yè)級(jí)主流方案

在 Spring 框架中,MyBatis 與 Spring 事務(wù)管理器深度整合,支持聲明式事務(wù)(通過(guò)@Transactional注解),無(wú)需手動(dòng)控制SqlSession的提交 / 回滾,簡(jiǎn)化事務(wù)代碼,是企業(yè)級(jí)開發(fā)的首選方案。

1. 核心原理

  • Spring 提供DataSourceTransactionManager作為事務(wù)管理器,該管理器通過(guò) MyBatis 的SqlSessionFactory獲取數(shù)據(jù)庫(kù)連接,統(tǒng)一管理事務(wù);
  • 當(dāng)方法添加@Transactional注解后,Spring 會(huì)通過(guò) AOP 動(dòng)態(tài)生成代理對(duì)象,在方法執(zhí)行前開啟事務(wù)(關(guān)閉 Connection 自動(dòng)提交),方法執(zhí)行成功后提交事務(wù),執(zhí)行失?。⊕伋霎惓#┖蠡貪L事務(wù);
  • Spring 事務(wù)管理器與 MyBatis 的SqlSession無(wú)縫協(xié)同:同一事務(wù)內(nèi),Spring 會(huì)確保所有 MyBatis 操作使用同一個(gè)SqlSession(綁定同一個(gè) Connection),保證事務(wù)原子性。

2. 實(shí)戰(zhàn)演示:Spring 聲明式事務(wù)整合 MyBatis

(1)環(huán)境準(zhǔn)備(Spring Boot + MyBatis)
  • 依賴配置(pom.xml):
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.10</version>
</parent>
<dependencies>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- MyBatis + Spring Boot整合依賴 -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.3.1</version>
    </dependency>
    <!-- MySQL驅(qū)動(dòng) -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
  • 配置文件(application.yml):
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test_mybatis?useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  # Spring事務(wù)配置(可選,默認(rèn)已配置DataSourceTransactionManager)
  transaction:
    rollback-on-commit-failure: true # 提交失敗時(shí)回滾
mybatis:
  mapper-locations: classpath:mapper/**/*.xml
  type-aliases-package: com.example.entity
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL,便于調(diào)試
(2)Service 層添加 @Transactional 注解
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private ProductMapper productMapper;
    /**
     * 下單流程:插入訂單 + 扣減庫(kù)存
     * @Transactional:聲明式事務(wù),默認(rèn) RuntimeException 觸發(fā)回滾
     */
    @Transactional(
            rollbackFor = Exception.class, // 所有異常都回滾(默認(rèn)僅RuntimeException回滾)
            propagation = Propagation.REQUIRED, // 事務(wù)傳播行為:默認(rèn),當(dāng)前無(wú)事務(wù)則創(chuàng)建新事務(wù)
            isolation = Isolation.DEFAULT // 隔離級(jí)別:默認(rèn),使用數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別
    )
    public void createOrder(Order order) {
        // 1. 插入訂單
        orderMapper.insertOrder(order);
        // 2. 扣減庫(kù)存
        int rows = productMapper.decreaseStock(order.getProductId(), order.getNum());
        if (rows == 0) {
            throw new RuntimeException("庫(kù)存不足,下單失敗");
        }
        // 3. 模擬其他業(yè)務(wù)操作(如記錄日志)
        System.out.println("下單成功,訂單號(hào):" + order.getOrderNo());
    }
}
(3)Controller 層測(cè)試
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @PostMapping
    public ResponseEntity<String> createOrder(@RequestBody Order order) {
        try {
            order.setOrderNo(UUID.randomUUID().toString());
            orderService.createOrder(order);
            return ResponseEntity.ok("下單成功");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("下單失敗:" + e.getMessage());
        }
    }
}

3. @Transactional 注解核心配置參數(shù)

@Transactional注解提供豐富的配置參數(shù),可根據(jù)業(yè)務(wù)需求調(diào)整事務(wù)行為,核心參數(shù)如下:

參數(shù)名作用說(shuō)明可選值
rollbackFor指定觸發(fā)回滾的異常類型(默認(rèn)僅 RuntimeException 及其子類回滾)Exception.class(所有異?;貪L)、SQLException.class(特定異?;貪L)
noRollbackFor指定不觸發(fā)回滾的異常類型BusinessException.class(業(yè)務(wù)異常不回滾)
propagation事務(wù)傳播行為(多事務(wù)方法嵌套時(shí)的行為)REQUIRED(默認(rèn))、SUPPORTS、REQUIRES_NEW、NESTED 等
isolation事務(wù)隔離級(jí)別(解決臟讀、不可重復(fù)讀、幻讀問(wèn)題)DEFAULT(默認(rèn),數(shù)據(jù)庫(kù)隔離級(jí)別)、READ_UNCOMMITTED、READ_COMMITTED 等
timeout事務(wù)超時(shí)時(shí)間(秒),超過(guò)時(shí)間未完成則自動(dòng)回滾30(30 秒超時(shí))
readOnly是否為只讀事務(wù)(僅查詢操作,設(shè)置為 true 可優(yōu)化性能,不可執(zhí)行增刪改)true/false(默認(rèn) false)
關(guān)鍵參數(shù)詳解:
  • 事務(wù)傳播行為:最常用REQUIRED(當(dāng)前無(wú)事務(wù)則創(chuàng)建新事務(wù),有事務(wù)則加入當(dāng)前事務(wù))和REQUIRES_NEW(無(wú)論當(dāng)前是否有事務(wù),都創(chuàng)建新事務(wù));
  • 事務(wù)隔離級(jí)別:企業(yè)級(jí)常用READ_COMMITTED(避免臟讀,大多數(shù)數(shù)據(jù)庫(kù)默認(rèn)級(jí)別),SERIALIZABLE(最高隔離級(jí)別,避免所有并發(fā)問(wèn)題,但性能最低);
  • readOnly:純查詢方法建議設(shè)置readOnly=true,Spring 會(huì)優(yōu)化事務(wù)配置(如關(guān)閉寫操作權(quán)限),提升查詢性能。

四、MyBatis 事務(wù)常見問(wèn)題與解決方案

1. 事務(wù)不生效問(wèn)題(高頻問(wèn)題)

問(wèn)題現(xiàn)象:

@Transactional注解添加后,事務(wù)未生效(部分操作成功、部分失敗時(shí)未回滾)。

常見原因與解決方案:
  • 原因 1:方法非 public 修飾:Spring AOP 僅對(duì) public 方法生成代理,非 public 方法的@Transactional注解無(wú)效;解決方案:確保事務(wù)方法為 public 修飾;
  • 原因 2:異常被 catch 捕獲未拋出:Spring 事務(wù)僅在方法拋出指定異常時(shí)才回滾,若異常被 try-catch 捕獲且未重新拋出,事務(wù)不會(huì)回滾;解決方案:捕獲異常后手動(dòng)拋出(如throw new RuntimeException(e)),或使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()手動(dòng)觸發(fā)回滾;
  • 原因 3:數(shù)據(jù)源未被 Spring 管理:MyBatis 的 SqlSessionFactory 未使用 Spring 的數(shù)據(jù)源,導(dǎo)致 Spring 事務(wù)管理器無(wú)法控制連接;解決方案:確保數(shù)據(jù)源通過(guò)spring.datasource配置,由 Spring 自動(dòng)注入;
  • 原因 4:內(nèi)部方法調(diào)用:同一類中無(wú)事務(wù)方法調(diào)用有事務(wù)方法,AOP 無(wú)法攔截,事務(wù)無(wú)效;解決方案:將事務(wù)方法抽取到其他 Service 類,或通過(guò)AopContext.currentProxy()獲取代理對(duì)象調(diào)用。

2. 事務(wù)并發(fā)問(wèn)題(臟讀、不可重復(fù)讀、幻讀)

問(wèn)題說(shuō)明:

多線程并發(fā)操作同一數(shù)據(jù)時(shí),可能出現(xiàn)以下問(wèn)題:

  • 臟讀:一個(gè)事務(wù)讀取到另一個(gè)事務(wù)未提交的數(shù)據(jù);
  • 不可重復(fù)讀:同一事務(wù)內(nèi)多次查詢同一數(shù)據(jù),結(jié)果不一致;
  • 幻讀:同一事務(wù)內(nèi)多次查詢,結(jié)果集行數(shù)不一致。
解決方案:
  • 調(diào)整事務(wù)隔離級(jí)別:如設(shè)置isolation = Isolation.READ_COMMITTED(避免臟讀)、Isolation.REPEATABLE_READ(避免臟讀和不可重復(fù)讀);
  • 加鎖:通過(guò)數(shù)據(jù)庫(kù)鎖(如行鎖、表鎖)或分布式鎖(Redis/ZooKeeper)控制并發(fā)訪問(wèn);
  • 避免長(zhǎng)事務(wù):長(zhǎng)事務(wù)會(huì)占用數(shù)據(jù)庫(kù)連接,增加并發(fā)沖突概率,盡量拆分長(zhǎng)事務(wù)為短事務(wù)。

3. 事務(wù)提交失敗問(wèn)題

問(wèn)題現(xiàn)象:

方法執(zhí)行無(wú)異常,但事務(wù)提交失敗(數(shù)據(jù)未入庫(kù))。

常見原因與解決方案:
  • 原因 1:數(shù)據(jù)庫(kù)引擎不支持事務(wù):如 MySQL 的 MyISAM 引擎不支持事務(wù),InnoDB 引擎支持;解決方案:將數(shù)據(jù)庫(kù)表引擎改為 InnoDB;
  • 原因 2:事務(wù)超時(shí):事務(wù)執(zhí)行時(shí)間超過(guò)timeout配置,被 Spring 自動(dòng)回滾;解決方案:優(yōu)化 SQL 執(zhí)行效率,或適當(dāng)增大timeout值;
  • 原因 3:連接池參數(shù)不合理:連接池最大連接數(shù)不足,導(dǎo)致事務(wù)無(wú)法獲取連接提交;解決方案:調(diào)整連接池參數(shù)(如spring.datasource.hikari.max-active)。

五、企業(yè)級(jí)實(shí)戰(zhàn):MyBatis 事務(wù)最佳實(shí)踐

1. 分層事務(wù)控制原則

  • 事務(wù)應(yīng)添加在 Service 層:Service 層負(fù)責(zé)業(yè)務(wù)邏輯整合,多步數(shù)據(jù)庫(kù)操作的事務(wù)控制應(yīng)在 Service 層統(tǒng)一管理,避免在 Controller 或 Mapper 層添加事務(wù);
  • 粒度適中:事務(wù)粒度不宜過(guò)大(避免長(zhǎng)事務(wù)),也不宜過(guò)?。ū苊馐聞?wù)碎片化),以 “一個(gè)完整業(yè)務(wù)場(chǎng)景” 為單位(如 “下單”“轉(zhuǎn)賬”)。

2. 高頻場(chǎng)景事務(wù)配置示例

(1)純查詢方法(只讀事務(wù))
// 純查詢方法,設(shè)置readOnly=true優(yōu)化性能
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public List<Order> getOrderByUserId(Long userId) {
    return orderMapper.selectByUserId(userId);
}
(2)轉(zhuǎn)賬業(yè)務(wù)(高一致性要求)
// 轉(zhuǎn)賬業(yè)務(wù):扣減付款方余額 + 增加收款方余額,要求強(qiáng)一致性
@Transactional(
        rollbackFor = Exception.class,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30
)
public void transfer(Long fromUserId, Long toUserId, BigDecimal amount) {
    // 扣減付款方余額
    userAccountMapper.decreaseBalance(fromUserId, amount);
    // 增加收款方余額
    userAccountMapper.increaseBalance(toUserId, amount);
}
(3)嵌套事務(wù)(REQUIRES_NEW)
// 主事務(wù):創(chuàng)建訂單
@Transactional(rollbackFor = Exception.class)
public void createOrder(Order order) {
    orderMapper.insertOrder(order);
    // 調(diào)用子事務(wù)方法(創(chuàng)建訂單日志,獨(dú)立事務(wù),即使失敗不影響主事務(wù))
    logService.recordOrderLog(order.getId());
}
// 子事務(wù):記錄訂單日志(獨(dú)立事務(wù))
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void recordOrderLog(Long orderId) {
    OrderLog log = new OrderLog();
    log.setOrderId(orderId);
    log.setOperateTime(LocalDateTime.now());
    orderLogMapper.insert(log);
}

3. 事務(wù)監(jiān)控與排查技巧

  • 開啟 Spring 事務(wù)日志:在 application.yml 中配置logging.level.org.springframework.transaction=DEBUG,可查看事務(wù)開啟、提交、回滾的詳細(xì)日志;
  • 打印 SQL 執(zhí)行日志:MyBatis 配置log-impl: org.apache.ibatis.logging.stdout.StdOutImpl,查看 SQL 執(zhí)行順序和參數(shù);
  • 數(shù)據(jù)庫(kù)事務(wù)日志:如 MySQL 的 binlog 日志,可排查事務(wù)提交是否寫入數(shù)據(jù)庫(kù)。

六、總結(jié)

MyBatis 事務(wù)的核心是 “通過(guò) SqlSession 控制數(shù)據(jù)庫(kù)連接的事務(wù)行為”,底層依賴 JDBC 事務(wù)機(jī)制,企業(yè)級(jí)開發(fā)中主要與 Spring 聲明式事務(wù)整合,通過(guò)@Transactional注解簡(jiǎn)化事務(wù)控制。掌握 MyBatis 事務(wù)的關(guān)鍵在于:

  1. 理解事務(wù)的 ACID 特性,明確事務(wù)的適用場(chǎng)景(多步數(shù)據(jù)庫(kù)操作需保證一致性);
  2. 區(qū)分原生 JDBC 事務(wù)和 Spring 聲明式事務(wù)的使用場(chǎng)景(非 Spring 環(huán)境用原生,Spring 環(huán)境用聲明式);
  3. 熟練配置@Transactional注解的核心參數(shù)(尤其是rollbackFor、propagationisolation);
  4. 規(guī)避常見問(wèn)題(如事務(wù)不生效、并發(fā)沖突、提交失敗),遵循分層事務(wù)控制原則。

在實(shí)際開發(fā)中,應(yīng)根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的事務(wù)策略:簡(jiǎn)單場(chǎng)景用 Spring 默認(rèn)配置,高一致性場(chǎng)景調(diào)整隔離級(jí)別和傳播行為,并發(fā)場(chǎng)景結(jié)合鎖機(jī)制,確保數(shù)據(jù)一致性和系統(tǒng)性能的平衡。

到此這篇關(guān)于MyBatis事務(wù)原理與實(shí)戰(zhàn)深入解析的文章就介紹到這了,更多相關(guān)MyBatis事務(wù)原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot時(shí)間格式化的方法小結(jié)

    SpringBoot時(shí)間格式化的方法小結(jié)

    SpringBoot中的時(shí)間格式化通常指的是將Java中的日期時(shí)間類型轉(zhuǎn)換為指定格式的字符串,或者將字符串類型的時(shí)間解析為Java中的日期時(shí)間類型,本文小編將給大家詳細(xì)總結(jié)了SpringBoot時(shí)間格式化的方法,剛興趣的小伙伴跟著小編一起來(lái)看看吧
    2023-10-10
  • 探討:如何在NDK中呼叫Java的class

    探討:如何在NDK中呼叫Java的class

    本篇文章是對(duì)如何在NDK中呼叫Java的class進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • SpringBoot應(yīng)用jar包啟動(dòng)原理詳解

    SpringBoot應(yīng)用jar包啟動(dòng)原理詳解

    本文主要介紹了SpringBoot應(yīng)用jar包啟動(dòng)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • 檢查Java環(huán)境變量是否配置成功的兩種方法

    檢查Java環(huán)境變量是否配置成功的兩種方法

    本文詳細(xì)介紹如何配置Java環(huán)境變量,包括設(shè)置JAVA_HOME路徑及添加到系統(tǒng)PATH中,確保Java命令行工具可用,同時(shí),演示了如何使用命令行編譯和運(yùn)行Java程序,以及使用javap工具進(jìn)行反匯編,需要的朋友可以參考下
    2026-03-03
  • @ControllerAdvice之全局異常處理過(guò)程

    @ControllerAdvice之全局異常處理過(guò)程

    文章介紹了在Java中處理異常的兩種方式:就地解決和向上拋出,并重點(diǎn)介紹了Spring框架中的@ControllerAdvice注解,用于實(shí)現(xiàn)全局異常處理,從而避免了在每個(gè)Controller類中重復(fù)編寫try-catch代碼塊,這種方法不僅提高了代碼的可維護(hù)性,還使得異常處理邏輯的修改更加方便
    2025-11-11
  • 實(shí)例解析使用Java實(shí)現(xiàn)基本的音頻播放器的編寫要點(diǎn)

    實(shí)例解析使用Java實(shí)現(xiàn)基本的音頻播放器的編寫要點(diǎn)

    這篇文章主要介紹了使用Java實(shí)現(xiàn)基本的音頻播放器的代碼要點(diǎn)實(shí)例分享,包括音頻文件的循環(huán)播放等功能實(shí)現(xiàn)的關(guān)鍵點(diǎn),需要的朋友可以參考下
    2016-01-01
  • MyBatis學(xué)習(xí)教程(三)-MyBatis配置優(yōu)化

    MyBatis學(xué)習(xí)教程(三)-MyBatis配置優(yōu)化

    這篇文章主要介紹了MyBatis學(xué)習(xí)教程(三)-MyBatis配置優(yōu)化的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-05-05
  • Java面試題之基本語(yǔ)法(圖解)

    Java面試題之基本語(yǔ)法(圖解)

    這篇文章主要介紹了關(guān)于Java面試題之基本語(yǔ)法的相關(guān)資料,文中通過(guò)圖片說(shuō)明介紹的很詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,有需要的朋友們下面來(lái)一起看看吧。
    2017-02-02
  • SpringBoot項(xiàng)目整合OpenFeign啟動(dòng)失敗及運(yùn)行時(shí)常見錯(cuò)誤解決方案

    SpringBoot項(xiàng)目整合OpenFeign啟動(dòng)失敗及運(yùn)行時(shí)常見錯(cuò)誤解決方案

    文章總結(jié)了在使用Feign進(jìn)行服務(wù)調(diào)用時(shí)可能遇到的常見問(wèn)題及其解決方案,涵蓋了依賴配置、接口定義、運(yùn)行時(shí)錯(cuò)誤和其它常見問(wèn)題的解決方法,建議使用兼容的版本、統(tǒng)一的包名結(jié)構(gòu),并為接口方法添加HTTP注解,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Linux下Java Python啟動(dòng)管理腳本方便程序管理

    Linux下Java Python啟動(dòng)管理腳本方便程序管理

    這篇文章主要為大家介紹了Linux下Java/Python啟動(dòng)管理腳本方便程序管理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11

最新評(píng)論

庄浪县| 广昌县| 白山市| 柏乡县| 垣曲县| 南投市| 金坛市| 安平县| 邯郸市| 顺昌县| 和硕县| 泸西县| 阜宁县| 江永县| 武夷山市| 罗城| 喀喇沁旗| 大同县| 葵青区| 荔浦县| 松阳县| 将乐县| 类乌齐县| 陇南市| 康平县| 怀柔区| 陇川县| 浪卡子县| 昂仁县| 洛浦县| 四子王旗| 根河市| 杭锦后旗| 滦南县| 湖南省| 华池县| 兖州市| 柯坪县| 阜南县| 墨脱县| 时尚|