MyBatis源碼解析-搭建調試環境

来源:https://www.cnblogs.com/liuzhiyong0718/archive/2020/03/11/12466294.html
-Advertisement-
Play Games

MyBatis源碼解析 搭建調試環境 1. 相關工具 Maven Git JDK1.8 IntelliJ IDEA 2. 源碼拉取 一般來說,我們直接從https://github.com/mybatis/mybatis 3 Fork到自己的倉庫中,為什麼要Fork呢?我們在之後的源碼分析中,我們可 ...


MyBatis源碼解析-搭建調試環境

1. 相關工具

  • Maven
  • Git
  • JDK1.8
  • IntelliJ IDEA

2. 源碼拉取

一般來說,我們直接從https://github.com/mybatis/mybatis-3 Fork到自己的倉庫中,為什麼要Fork呢?我們在之後的源碼分析中,我們可能會加一些註釋,英文翻譯一波,方便自己理解,也方便自己自由提交。

  • 版本:3.5.4-SNAPSHOT

3. 調試

啥也不多說,咱們直接看單元測試結構,除了autoconstructor這個包下是整體調試以外,其他的都是各個模塊的單元測試。那咱們直接就從org.apache.ibatis.autoconstructor這個包下開始調試。

從這個包下主要包含下麵幾部分,如圖所示:

  • MyBatis的配置文件:mybatis-config.xml

  • SQL文件: CreateDB.sql

  • 映射及配置:AutoConstructorMapper.java AutoConstructorMapper.xml

  • 實體類:AnnotatedSubject.java BadSubject.java ExtensiveSubject.java PrimitiveSubject.java

  • 測試類:AutoConstructorTest.java

3.1 MyBatis的配置文件

mybatis-config.xml 作為MyBatis的配置文件,xml配置代碼如下:

<?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>
    <!-- autoMappingBehavior should be set in each test case -->

    <!--  環境配置  -->
    <environments default="development">
        <environment id="development">
            <!-- 事務管理配置 -->
            <transactionManager type="JDBC">
                <property name="" value=""/>
            </transactionManager>
            <!-- 數據源配置 -->
            <dataSource type="UNPOOLED">
                <property name="driver" value="org.hsqldb.jdbcDriver"/>
                <property name="url" value="jdbc:hsqldb:mem:automapping"/>
                <property name="username" value="sa"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 掃描的Mapper文件 -->
    <mappers>
        <mapper resource="org/apache/ibatis/autoconstructor/AutoConstructorMapper.xml"/>
    </mappers>

</configuration>

  • 環境配置:在</environment>標簽中,配置了事務管理和數據源,資料庫選擇方面使用了HSQLDB,減少外部依賴。
  • 掃描映射:在<mappers>配置了要掃描的Mapper文件,這裡只配置了AutoConstructorMapper.xml。

3.2 SQL文件

CreateDB.sql 在單元測試中用作初始化資料庫的表及數據。如下:


DROP TABLE subject
IF EXISTS;

DROP TABLE extensive_subject
IF EXISTS;

CREATE TABLE subject (
  id     INT NOT NULL,
  name   VARCHAR(20),
  age    INT NOT NULL,
  height INT,
  weight INT,
  active BIT,
  dt     TIMESTAMP
);

CREATE TABLE extensive_subject (
  aByte      TINYINT,
  aShort     SMALLINT,
  aChar      CHAR,
  anInt      INT,
  aLong      BIGINT,
  aFloat     FLOAT,
  aDouble    DOUBLE,
  aBoolean   BIT,
  aString    VARCHAR(255),
  anEnum     VARCHAR(50),
  aClob      LONGVARCHAR,
  aBlob      LONGVARBINARY,
  aTimestamp TIMESTAMP
);

INSERT INTO subject VALUES
  (1, 'a', 10, 100, 45, 1, CURRENT_TIMESTAMP),
  (2, 'b', 10, NULL, 45, 1, CURRENT_TIMESTAMP),
  (2, 'c', 10, NULL, NULL, 0, CURRENT_TIMESTAMP);

INSERT INTO extensive_subject
VALUES
  (1, 1, 'a', 1, 1, 1, 1.0, 1, 'a', 'AVALUE', 'ACLOB', 'aaaaaabbbbbb', CURRENT_TIMESTAMP),
  (2, 2, 'b', 2, 2, 2, 2.0, 2, 'b', 'BVALUE', 'BCLOB', '010101010101', CURRENT_TIMESTAMP),
  (3, 3, 'c', 3, 3, 3, 3.0, 3, 'c', 'CVALUE', 'CCLOB', '777d010078da', CURRENT_TIMESTAMP);

包含兩張表:subject表和extensive_subject表。

3.3 映射及配置

包含AutoConstructorMapper.java AutoConstructorMapper.xml兩個文件

3.3.1 AutoConstructorMapper.java

package org.apache.ibatis.autoconstructor;

import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface AutoConstructorMapper {
  // PrimitiveSubject
  @Select("SELECT * FROM subject WHERE id = #{id}")
  PrimitiveSubject getSubject(final int id);

  // PrimitiveSubject
  @Select("SELECT * FROM subject")
  List<PrimitiveSubject> getSubjects();

  // AnnotatedSubject
  @Select("SELECT * FROM subject")
  List<AnnotatedSubject> getAnnotatedSubjects();
  
  // BadSubject
  @Select("SELECT * FROM subject")
  List<BadSubject> getBadSubjects();

  // ExtensiveSubject
  @Select("SELECT * FROM extensive_subject")
  List<ExtensiveSubject> getExtensiveSubjects();
}
  • 使用註解方式配置mapper,在開發中基於xml配置的還是用的多一些,比較靈活。推薦xml配置。

3.3.2 AutoConstructorMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.apache.ibatis.autoconstructor.AutoConstructorMapper">
</mapper>
  • 映射介面:org.apache.ibatis.autoconstructor.AutoConstructorMapper

3.4 實體類

3.4.1 AnnotatedSubject.java

​ AnnotatedSubject類中除了欄位還有預設的構造函數以外,還提供一個以基本數據包裝類作為構造參數的構造函數。註:@AutomapConstructor 這個註解的作用是讓框架自動使用這個構造器。【這裡重點說一下,我們在使用MyBatis的時候,實體類的欄位類型最好使用包裝類,最好不要設置預設值,否則xml里處理會有些麻煩。

package org.apache.ibatis.autoconstructor;  

import org.apache.ibatis.annotations.AutomapConstructor;

public class AnnotatedSubject {
  private final int id;
  private final String name;
  private final int age;
  private final int height;
  private final int weight;


  public AnnotatedSubject(final int id, final String name, final int age, final int height,   final int weight) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.height = height;
    this.weight = weight;
  }

  //自動映射構造器 基本類型包裝類作為構造參數
  @AutomapConstructor
  public AnnotatedSubject(final int id, final String name, final int age, final Integer height, final Integer weight) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.height = height == null ? 0 : height;
    this.weight = weight == null ? 0 : weight;
  }
}
  • 對應subject
  • 使用自動映射構造器註解@AutomapConstructor,開發過程中我很少用到。
3.4.1.1 PrimitiveSubject.java
package org.apache.ibatis.autoconstructor;

import java.util.Date;

public class PrimitiveSubject {
  private final int id;
  private final String name;
  private final int age;
  private final int height;
  private final int weight;
  private final boolean active;
  private final Date dt;

  public PrimitiveSubject(final int id, final String name, final int age, final int height, final int weight, final boolean active, final Date dt) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.height = height;
    this.weight = weight;
    this.active = active;
    this.dt = dt;
  }
}
3.4.1.2 BadSubject.java
package org.apache.ibatis.autoconstructor;

public class BadSubject {
  private final int id;
  private final String name;
  private final int age;
  private final Height height;
  private final Double weight;

  public BadSubject(final int id, final String name, final int age, final Height height, final Double weight) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.height = height;
    this.weight = weight == null ? 0 : weight;
  }

  private class Height {

  }
}
  • 對應subject

  • 和上面AnnotatedSubject類的構造函數不同,在其構造參數中使用類型 Height,而不是Integer。因為MyBatis找不到Height映射的配置,所以在構造BadSubject對象的時候會報錯。

    3.4.2 ExtensiveSubject.java

    package org.apache.ibatis.autoconstructor;
    
    public class ExtensiveSubject {
        private final byte aByte;
        private final short aShort;
        private final char aChar;
        private final int anInt;
        private final long aLong;
        private final float aFloat;
        private final double aDouble;
        private final boolean aBoolean;
        private final String aString;
    
        // enum types
        private final TestEnum anEnum;
    
        // array types
    
        // string to lob types:
        private final String aClob;
        private final String aBlob;
    
        public ExtensiveSubject(final byte aByte,
                                final short aShort,
                                final char aChar,
                                final int anInt,
                                final long aLong,
                                final float aFloat,
                                final double aDouble,
                                final boolean aBoolean,
                                final String aString,
                                final TestEnum anEnum,
                                final String aClob,
                                final String aBlob) {
            this.aByte = aByte;
            this.aShort = aShort;
            this.aChar = aChar;
            this.anInt = anInt;
            this.aLong = aLong;
            this.aFloat = aFloat;
            this.aDouble = aDouble;
            this.aBoolean = aBoolean;
            this.aString = aString;
            this.anEnum = anEnum;
            this.aClob = aClob;
            this.aBlob = aBlob;
        }
    
        public enum TestEnum {
            AVALUE, BVALUE, CVALUE;
        }
    }
  • 對應extensive_subject
  • 相對於AnnotatedSubject這個稍微複雜一些,對象屬性幾乎包含了所有類型的數據。

3.5 測試類

對應AutoConstructorTest.java文件,單元測試類。

3.5.1 setUp

@BeforeAll
static void setUp() throws Exception {
  // create a SqlSessionFactory
  //讀取 mybatis-config.xml 配置創建 SqlSessionFactory 對象
  try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/autoconstructor/mybatis-config.xml")) {
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
  }

  // populate in-memory database
  // 讀取CreateDB.sql文件初始化數據到記憶體資料庫中
  BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
      "org/apache/ibatis/autoconstructor/CreateDB.sql");
}
  • @BeforeAll 這個註解是JUnit5提供的一個註解,作用:註釋的靜態方法會在執行所有測試用例之前調用,其他詳細介紹可以參考 JUnit4與JUnit5註解對比
  • 讀取 mybatis-config.xml 配置創建 SqlSessionFactory 對象
  • 讀取CreateDB.sql文件初始化數據到記憶體資料庫中

3.5.2 Run Test

右鍵任意一個測試方法debug搞起來。IDEA調試技巧

本文由 Janker 創作,採用 CC BY 3.0 CN協議 進行許可。 可自由轉載、引用,但需署名作者且註明文章出處。如轉載至微信公眾號,請在文末添加作者公眾號二維碼。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • etcd是什麼? etcd是一個用Go語言寫的,用於分散式系統下高性能的鍵值(K V)存儲、服務發現、負載均衡、、分散式鎖、配置管理等場景地應用,類似於Java的zookeeper。基於Raft協議,能保證數據的一致性。 官方地址 [etcd.io] https://etcd.io [github. ...
  • 什麼是池,我們在開發中經常會聽到有線程池啊,資料庫連接池等等。那麼到底什麼是池?其實很簡單,裝水的池子就叫水池嘛,用來裝線程的池子就叫線程池(廢話),就是我們把創建好的N個線程都放在一個池子裡面,如果有需要,我們就去取,不用額外的再去手動創建了為什麼要用線程池按照正常的想法是,我們需要一個線程,就去... ...
  • springboot的優質開發體驗,能夠更快速的搭建生產環境的項目。這篇文章就是一個超級簡單的入門springboot項目。包含了一些簡單的理論和超簡單Controller層 【工具】 IDEA 全稱IntelliJ IDEA SpringBoot 【創建項目】打開IDEA編輯器,新建項目,然後選擇 ...
  • MyBatis源碼解析 反射模塊 1. 前言 ​ 該模塊位於 包中,MyBatis在進行參數處理、結果映射等操作時,會涉及大量的反射操作。Java 中的反射雖然功能強大,但是代碼編寫起來比較複雜且容易出錯,為了簡化反射操作的相關代碼,MyBatis提供了專門的反射模塊,它對常見的反射操作做了進一步封 ...
  • this語句:用於構造函數之間進行相互調用 this(屬性) this()語句只能定義在構造函數的第一行。因為初始化動作要先執行。 ...
  • Thread.join中使用Object.wait實現: //java.lang.Thread public final synchronized void join(long millis) throws InterruptedException { long base = System.curr ...
  • MyBatis源碼解析 解析器模塊 1. 前言 在MyBatis中涉及多個xml文件,解析這些xml文件自然離不開解析器。本文就來分析一下解析器模塊。 2. 準備工作 xml常見的解析方式分為以下三種: DOM ( Document Object Model)解析方式 SAX (Simple API ...
  • MyBatis 源碼分析 項目總覽 1.概述 本文主要大致介紹一下MyBatis的項目結構。 引用參考資料《MyBatis技術內幕》 此外,https://mybatis.org/mybatis 3/zh/index.html MyBatis官方也提供了很不錯的中文文檔。對於使用中有碰到一些問題,可 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...