通常來講,咱們直接從https://github.com/mybatis/mybatis-3 Fork到本身的倉庫中,爲何要Fork呢?咱們在以後的源碼分析中,咱們可能會加一些註釋,英文翻譯一波,方便本身理解,也方便本身自由提交。java
啥也很少說,我們直接看單元測試結構,除了autoconstructor
這個包下是總體調試之外,其餘的都是各個模塊的單元測試。那我們直接就從org.apache.ibatis.autoconstructor
這個包下開始調試。git
從這個包下主要包含下面幾部分,如圖所示:github
MyBatis的配置文件:mybatis-config.xmlsql
SQL文件: CreateDB.sql數據庫
映射及配置:AutoConstructorMapper.java AutoConstructorMapper.xmlapache
實體類:AnnotatedSubject.java BadSubject.java ExtensiveSubject.java PrimitiveSubject.java微信
測試類:AutoConstructorTest.javamybatis
見mybatis-config.xml
做爲MyBatis的配置文件,xml配置代碼以下:app
<?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。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
表。
包含AutoConstructorMapper.java AutoConstructorMapper.xml兩個文件
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(); }
<?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
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
,開發過程當中我不多用到。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; } }
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對象的時候會報錯。
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這個稍微複雜一些,對象屬性幾乎包含了全部類型的數據。
對應AutoConstructorTest.java文件,單元測試類。
@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"); }
右鍵任意一個測試方法debug搞起來。IDEA調試技巧
本文由 Janker 創做,採用 CC BY 3.0 CN協議 進行許可。 可自由轉載、引用,但需署名做者且註明文章出處。如轉載至微信公衆號,請在文末添加做者公衆號二維碼。