mybatis源码解析之简单案例(一)

mybatis简单案例

完整的目录

这里写图片描述

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>
    <!--properties内容-->
    <properties>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;zeroDateTimeBehavior=convertToNull"/>
        <property name="username" value="root"/>
        <property name="password" value="liu2126962"/>
    </properties>
    <!--全局设置-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="useGeneratedKeys" value="true"/>
        <!--<setting name="autoMappingUnknownColumnBehavior" value="FAILING"/>-->
        <!--<setting name="cacheEnabled" value="true"/>-->
        <!--<setting name="useColumnLabel" value="true"/>-->
        <!--<setting name="lazyLoadingEnabled" value="true"/>-->
        <!--<setting name="multipleResultSetsEnabled" value="true"/>-->
        <!-- 是否打印SQL日志.-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--重命名-->
    <typeAliases>
    </typeAliases>
    <!--类型转换映射-->
    <typeHandlers>
    </typeHandlers>
    <!--环境的配置-->
    <environments default="dev">
        <environment id="dev">
            <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>
    <!--插件
    <plugins>
    </plugins>-->
    <!--对应的映射-->
    <mappers>
        <!--扫描某一个包-->
        <!--<package name="com.liubin.study.mybatis.object"/>-->
        <!--扫描某一个类-->
        <!--<mapper class="com.liubin.study.mybatis.object.ISupplierLabelDAO"/>-->
        <!--扫描某个mapper文件-->
        <mapper resource="mapper/supplier-label-mapper.xml"/>
    </mappers>
</configuration>

supplier-label-mapper.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="com.liubin.study.mybatis.object.ISupplierLabelDAO">
    <sql id="selectFields">
        SELECT
        label.id,
        label.supplier_type,
        label.supplier_id,
        label.label_type,
        label.label_id,
        label.label_name,
        label.gmt_created,
        label.gmt_modified
        FROM supplier_label label
    </sql>
    <!--根据ID查询-->
    <select id="selectById" resultType="com.liubin.study.mybatis.object.dataobject.SupplierLabelDO">
        <include refid="selectFields"/>
        <where>
            label.id = #{id}
        </where>
    </select>
</mapper>

SimpleTest.class

public class SimpleTest {
    private final static Logger LOGGER = LoggerFactory.getLogger(SimpleTest.class);
    public SqlSessionFactory buildFactory() {
        try {
            InputStream inputStream = Resources.getResourceAsStream("config/mybatis.xml");
            return new SqlSessionFactoryBuilder().build(inputStream,"dev");
        } catch (Exception e) {
            LOGGER.error("构建SqlSessionFactory失败", e);
        }
        return null;
    }
    @Test
    public void testMapper(){
        SqlSessionFactory factory = buildFactory();
        SqlSession session = factory.openSession();
        try{
            ISupplierLabelDAO supplierLabelDAO = session.getMapper(ISupplierLabelDAO.class);
            SupplierLabelDO labelDO = supplierLabelDAO.selectById(1L);
            System.out.println(labelDO);
        }catch (Exception e){
            LOGGER.error("执行查询SQL失败",e);
        }finally {
            session.close();
        }
    }
}

mybatis之核心类

从上面的测试代码中,我们可以看到,首先mybatis.xml文件加载为流,然后根据流来构建mybatis的SqlSessionFactory。再根据SqlSessionFactory来来构建SqlSession。

  • SqlSessionFactoryBuilder 类仅仅用来构建SqlSessionFactory类,在构建出SqlSessionFactory实例后,SqlSessionFactoryBuilder就可以被抛弃了。(在每一个Application中,我们应该保证只会存在一个SqlSessionFactory)。
public class SqlSessionFactoryBuilder {

  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }

  public SqlSessionFactory build(Reader reader, String environment) {
    return build(reader, environment, null);
  }

  public SqlSessionFactory build(Reader reader, Properties properties) {
    return build(reader, null, properties);
  }

  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        reader.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }

  public SqlSessionFactory build(InputStream inputStream, String environment) {
    return build(inputStream, environment, null);
  }

  public SqlSessionFactory build(InputStream inputStream, Properties properties) {
    return build(inputStream, null, properties);
  }

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

  /**
   * 最根本的build方法,上方的所有build方法最终都会调用此方法
   * 需要一个Configuration作为参数
   **/
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
  • SqlSessionFactory类 用来进行构建SqlSession
    我们可以看到默认的SqlSessionFactory中只包含了一个变量域Configuration,这个参数由SqlSessionFactoryBuilder中的函数进行构建。由此,我们可以知道对于所有mybatis配置和映射,都是存储在Configuration中,根据这些再构建SqlSessionFactory。
public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private final Configuration configuration;

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }
  ....
}
  • SqlSession类,则是构建出来的用来进行执行SQL的会话
    查看默认的SqlSession,我们可以看到里面包含一个Configuration和一个Executor,Configuration中存储了所有的配置,Executor则是用来进行执行SQL的执行接口。
public class DefaultSqlSession implements SqlSession {

  private Configuration configuration;
  private Executor executor;

  private boolean autoCommit;
  private boolean dirty;
  private List<Cursor<?>> cursorList;

  public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }
}

猜你喜欢

转载自blog.csdn.net/liu20111590/article/details/81293649