美文网首页
Mybatis学习总结(一)SqlSessionFactory

Mybatis学习总结(一)SqlSessionFactory

作者: john_leventon | 来源:发表于2019-02-01 19:48 被阅读0次

    写给自己的:经过半个月Mybatis的学习,对Mybatis的基本用法有了一定的掌握。但是以往学习其它框架的经历告诉我,学习完后不抓紧总结很快又会忘记,遂从头开始梳理总结一遍。从Mybatis的核心组件入手是有效梳理和总结Mybatis框架的有效路径,这些总结不会深入底层框架的源码,专注于上层接口和类的一些分析,因为本人的开发经验都还很欠缺,过早去纠结源码收获必不多。

    Mybatis的核心组件有:SqlSessionFactory、SqlSession、Mapper、TypeHandler。前面对它们的总结主要是集中于使用环节,这个系列将集中于它们比较浅显的创建过程和更加细节性的东西。本系列针对Mybatis3.4.5源码进行阐述。

    一、SqlSessionFactory

    1、细说SqlSessionFactory创建过程

    SqlSessionFactory由SqlSessionFactoryBuilder通过xml配置文件或者Configuration配置类对象产生。

    我们通常是通过

     InputStream is = Resources.getResourceAsStream(String baseConfigXmlFilePath);

    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is)

    这两个步骤获取SqlSessionFactory接口对象

    那么其中Mybatis帮我们做了哪些事呢?

    首先看SqlSessionFactoryBuilder这个类

    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.

          }

        }

      }

      public SqlSessionFactory build(Configuration config) {

        return new DefaultSqlSessionFactory(config);

      }

    }

    从SqlSessionFactoryBuilder这个类的源码中可以看出,它有9个build方法的重载。

    根本的有三个重载的build方法:

    1、  public SqlSessionFactory build(Reader reader, String environment, Properties properties)

    2、  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties)

    3、  public SqlSessionFactory build(Configuration config)


    结合Mybatis的基础配置文件结构,整个SqlSessionFactory的创建过程就非常明了了。<Configuration>与Configuration配置类对应,它涵盖了创建SqlSessionFactory所需要的全部配置信息。

    整个流程如下:

    baseConfigXmlFile-------------->XmlConfigBuilder解析---------->Configuration类对象----------->SqlSessionFactoryBuilder--------------->SqlSessionFactory对象。

    接下来细说下面这个方法:

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties)

    enviroment是指定默认的数据库环境如下所示

    <environments default="development">

          <environment id="development">

            <transactionManager type="JDBC" />

            <dataSource type="POOLED">

              <property name="driver" value="com.mysql.jdbc.Driver" />

              <property name="driver.encoding" value="utf8" />

              <property name="url" value="jdbc:mysql://localhost/book"/>

              <property name="username" value="root" />

              <property name="password" value="123456" />

            </dataSource>

          </environment>

        </environments>

    当这个参数不为null时,将覆盖基础配置文件中的值,可以在一个基础配置文件中配置多个数据库环境,然后在创建不同数据库的SqlSessionFactory比如存在数据库环境配置db1、db2

    <environments default="development">

          <environment id="db1">

    ......

          </environment>

    <environment id="db2">

    ......

          </environment>

        </environments>

    String baseConfigFilePath = "mybatis-config.xml";

    InputStream is1 = Resources.getResourceAsStream(baseConfigFilePath);

    InputSream is2 = Resources.getResourceAsStream(baseConfigFilePath);

    SqlSessionFactory db1SqlSessionFactory = new SqlSessionFactoryBuilder().build(is1, "db1");

    SqlSessionFactory db1SqlSessionFactory = new SqlSessionFactoryBuilder().build(is2, "db2");

    注意这里:虽然配置文件是同一个,但是不能共享同一个InputSream对象,因为SqlSessionFactoryBuilder在创建完SqlSessionFactory对象后会关闭InputStream对象。

    再看properties这个参数,可以通过properties参数配置属性信息,同样它将覆盖基础配置文件中的相同属性名称的属性的值。

    String resource = "mybatis-config.xml"//基础配置文件

    InputStream inputStream;

    InputSream is = Resource.getResourceAsStream("jdbc.properties");

    Properties props = new Properties();

    props.load(is);

    String userName = props.getProperty("database.username");

    String password = props.getProperty("database.password");

    //解密用户名和密码

    props.put("database.username", CodeUtils.decode(userName));

    props.put("database.password", CodeUtils.decode(password));

    inputStream = Resource.getResourceAsStream(resource);

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream, props);

    三种配置方式优先级:代码方式>properties文件方式>property子元素方式

    当SqlSessionFactory对象创建完成后,我们如果需要修改配置信息怎么办呢?

    SqlSessionFactory对象保存了创建它的Configuration对象的信息,我们可以通过

    SqlSessionFactory对象的getConfiguration()方法获取Configuration配置对象。

    而Confiration配置对象中,保存了各种注册器的引用(别名注册器、类型转换器等)


    可以通过这些方法动态地改变配置信息。如我们可以获取别名注册器在代码中动态地注册别名:

    Configuration configuration = factory.getConfiguration();

    TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();

    typeAliasRegistry.registerAlias("key", "value");

    相关文章

      网友评论

          本文标题:Mybatis学习总结(一)SqlSessionFactory

          本文链接:https://www.haomeiwen.com/subject/gxmdsqtx.html