Mybatis学习总结(一)SqlSessionFactory

写给自己的:经过半个月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");

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,873评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,483评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,525评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,595评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,018评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,958评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,118评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,873评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,643评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,813评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,293评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,615评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,306评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,170评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,968评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,107评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,894评论 2 278

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,288评论 0 4
  • ORM框架Mybatis几个重要的流程: SqlSessionFactoryBuilder,用来创建SqlSess...
    小雪的笔记阅读 405评论 0 1
  • MyBatis 理论篇 [TOC] 什么是MyBatis  MyBatis是支持普通SQL查询,存储过程和高级映射...
    有_味阅读 2,809评论 0 26
  • MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC...
    慕容小伟阅读 978评论 0 2
  • lambda表达式(又被成为“闭包”或“匿名方法”)方法引用和构造方法引用扩展的目标类型和类型推导接口中的默认方法...
    183207efd207阅读 1,422评论 0 5