MyBatis源码解析-搭建调试环境

2020-03-11  本文已影响0人  janker0718

MyBatis源码解析-搭建调试环境

1. 相关工具

2. 源码拉取

一般来说,我们直接从https://github.com/mybatis/mybatis-3 Fork到自己的仓库中,为什么要Fork呢?我们在之后的源码分析中,我们可能会加一些注释,英文翻译一波,方便自己理解,也方便自己自由提交。

3. 调试

啥也不多说,咱们直接看单元测试结构,除了autoconstructor这个包下是整体调试以外,其他的都是各个模块的单元测试。那咱们直接就从org.apache.ibatis.autoconstructor这个包下开始调试。

从这个包下主要包含下面几部分,如图所示:

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>


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();
}

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>

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;
  }
}

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 {

  }
}

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");
}

3.5.2 Run Test

右键任意一个测试方法debug搞起来。IDEA调试技巧

本文由 Janker 创作,采用 CC BY 3.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
<img src="http://qiniu-cdn.janker.top/oneblog/20200311150833864.jpg" style="zoom:50%;" />

上一篇 下一篇

猜你喜欢

热点阅读