mybatis全局配置文件详解

红太狼 2024-04-07 14:14 119阅读 0赞

mybatis全局配置文件详解

  • 一,orm介绍
  • 2,JDBC
    • 2.1四大核心对象
    • 2.1 JDBC出现一些的问题
  • 三,mybatis功能架构
  • 四,mybatis源码解析
    • 1,构造对象流程
    • 2,加载流程源码分析
  • 五,总结

一,orm介绍

  1. o <===> object
  2. r <===> relational
  3. m <===> mapping

MyBatis:是一个持久层框架,使用简单,学习成本较低。可以执行自己手写的sql语句,比较灵活,但是mybatis的自动程度画不高,移植性也不高,从一个数据库迁移到另外一个数据库的时候需要修改配置,所以被称为半自动化ORM框架

Hibernate:底层实现了很多add方式,所以被称为全自动ORM框架

2,JDBC

2.1四大核心对象

1,加载驱动

  1. Class.forName("com.mysql.jdbc.Driver")

2,创建连接

  1. COnnection con = DriverManager.getConnection(...)

3,获取sql执行者,执行操作

  1. con.prepareStament(sql)

4,执行查询

  1. execute();

5,关闭数据库,关闭连接

  1. .close()

2.1 JDBC出现一些的问题

1,数据库配置,sql语句在代码中出现硬编码的问题,mybatis通过xml解决
2,jdbc频繁的创建和关闭数据库链接,对数据库是一个很大的消耗,mybatis通过数据库连接池解决。
3,参数设置不方便,mybatis 通过动态sql查询
4,处理结果集不方便,mybatis 可以自定义 resultMap 进行映射

三,mybatis功能架构

API接口层:提供给外部使用的接口api,可以通过这些api来操纵数据库

数据处理层:负责具体的sql查找、解析、执行和映射结果处理等

基础支撑层:负责最基础功能的支撑,如一些连接管理,事务管理,配置加载,缓存等。

可以通过这份笔记来对这个mybatis有一个基本的了解:https://note.youdao.com/ynoteshare/index.html?id=5d41fd41d970f1af9185ea2ec0647b64&type=notebook&_time=1662564167792

四,mybatis源码解析

1,构造对象流程

  1. String resource = "mybatis-config.xml";
  2. Reader reader;
  3. //将XML配置文件构建为Configuration配置类
  4. reader = Resources.getResourceAsReader(resource);
  5. // 通过加载配置文件流构建一个SqlSessionFactory DefaultSqlSessionFactory
  6. SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
  7. // 数据源 执行器 DefaultSqlSession
  8. SqlSession session = sqlMapper.openSession();
  9. //解析配置类
  10. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  11. //其底层就是专门用来解析xml的,xml里面的任何一个配置文件,都是通过node存储的
  12. //可以通过node来获取里面的属性和里面的值,可以获取配置文件下面的所有的值
  13. Node node = (Node)new XPathParser();
  14. //调用parse方法解析 这个全局配置文件
  15. parser.parse()
  16. //解析mybatis-config.xml的node节点
  17. parseConfiguration(parser.evalNode("/configuration"))

2,加载流程源码分析

1,先查看这个SqlSessionFactoryBuilder看看底层的具体流程,其主要就是加载配置文件,将这些文件加载一个configuration的一个对象里面。

  1. SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);

2,这个Configuration会包含很多东西,如一些环境,缓存等等等

  1. public class Configuration {
  2. //环境
  3. protected Environment environment;
  4. protected boolean safeRowBoundsEnabled;
  5. protected boolean safeResultHandlerEnabled = true;
  6. protected boolean mapUnderscoreToCamelCase;
  7. protected boolean aggressiveLazyLoading;
  8. protected boolean multipleResultSetsEnabled = true;
  9. protected boolean useGeneratedKeys;
  10. protected boolean useColumnLabel = true;
  11. //缓存
  12. protected boolean cacheEnabled = true;
  13. protected boolean callSettersOnNulls;
  14. protected boolean useActualParamName = true;
  15. protected boolean returnInstanceForEmptyRow;
  16. ...
  17. }

3,其build方法如下,主要是通过这个责任链模式,单参调双参,双参调三参。

  1. public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
  2. try {
  3. //获取配置文件
  4. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  5. //解析配置文件
  6. return build(parser.parse());
  7. }finally{
  8. reader.close();
  9. }
  10. }

在这个解析配置文件的方法里面,会有一个parseConfiguration的类

  1. public Configuration parse() {
  2. parseConfiguration(parser.evalNode("/configuration"));
  3. return configuration;
  4. }

接下来主要查看这个parseConfiguration类,就是对应xml里面的configuration标签里面的一些标签
在这里插入图片描述

  1. private void parseConfiguration(XNode root) {
  2. //解析properties标签
  3. propertiesElement(root.evalNode("properties"));
  4. //解析settings标签
  5. Properties settings = settingsAsProperties(root.evalNode("settings"));
  6. //解析environments环境标签
  7. environmentsElement(root.evalNode("environments"));
  8. //解析typeAliases别名标签
  9. typeAliasesElement(root.evalNode("typeAliases"));
  10. //解析typeHandlers标签
  11. typeHandlerElement(root.evalNode("typeHandlers"));
  12. //解析mappers标签
  13. mapperElement(root.evalNode("mappers"));
  14. }

4,解析这个配置文件的propertiesElement方法如下,里面的parse解析方法采用的是一个责任链模式

  1. private void propertiesElement(XNode context) throws Exception {
  2. if (context != null) {
  3. //获取子结点
  4. Properties defaults = context.getChildrenAsProperties();
  5. //获取资源
  6. String resource = context.getStringAttribute("resource");
  7. //最后将这个Properties对象加入到这个configuration的配置文件里面
  8. configuration.setVariables(defaults);
  9. }
  10. }

其他的标签也是会通过这个责任链模式,对这些标签进行解析,并最终会加入到这个configuration的配置里面

5,一直到最后一个,会去解析这个mapper里面的mappers这个配置文件。会通过这个mapper的这个类,比如说UserMapper,然后找到对应的xml文件。

  1. <mappers>
  2. <package name="com.tuling.mapper"/>
  3. </mappers>

其源码实现如下,在解析这个config.xml的配置文件之后,会解析这个mapper.xml的映射文件

  1. private void mapperElement(XNode parent) throws Exception {
  2. //创建读取XmlMapper构建器对象
  3. XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
  4. //开始真正的解析mapper的xml文件
  5. mapperParser.parse();
  6. }

进入这个解析映射文件的方法

  1. public void parse() {
  2. //获取mapper映射文件的所有内容,并对映射文件进行解析
  3. configurationElement(parser.evalNode("/mapper"));
  4. }

在进入这个configurationElement的这个方法

  1. private void configurationElement(XNode context) {
  2. //会先解析mapper标签里面的这个namespace的这个标签
  3. String namespace = context.getStringAttribute("namespace");
  4. //设置到这个build的助手里面
  5. builderAssistant.setCurrentNamespace(namespace);
  6. //解析当前的缓存的引用
  7. cacheRefElement(context.evalNode("cache-ref"));
  8. //解析这个二级缓存
  9. cacheElement(context.evalNode("cache"));
  10. //解析resultMapper文件
  11. resultMapElements(context.evalNodes("/mapper/resultMap"));
  12. //解析sql片段
  13. sqlElement(context.evalNodes("/mapper/sql"));
  14. //解析数据的增删改查
  15. buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
  16. }

6,再查看解析mapper里面的二级缓存,cacheElement方法如下,缓存的过期策略为一个LRU

  1. private void cacheElement(XNode context) {
  2. //解析cache节点的type属性
  3. String type = context.getStringAttribute("type", "PERPETUAL");
  4. //根据type的String获取class类型
  5. Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
  6. //获取缓存过期策略:默认是LRU
  7. String eviction = context.getStringAttribute("eviction", "LRU");
  8. Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
  9. //flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。
  10. Long flushInterval = context.getLongAttribute("flushInterval");
  11. //size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
  12. Integer size = context.getIntAttribute("size");
  13. //只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false
  14. boolean readWrite = !context.getBooleanAttribute("readOnly", false);
  15. boolean blocking = context.getBooleanAttribute("blocking", false);
  16. Properties props = context.getChildrenAsProperties();
  17. //把缓存节点加入到Configuration中
  18. builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
  19. }

7,再查看这个解析数据的增删改查,会对文件里面的增删改查语句进行解析

  1. private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
  2. for (XNode context : list) {
  3. //解析增删改查结点
  4. final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
  5. try {
  6. statementParser.parseStatementNode();
  7. } catch (IncompleteElementException e) {
  8. configuration.addIncompleteStatement(statementParser);
  9. }
  10. }
  11. }

五,总结

1,首先会创建一个SqlSessionFactoryBuilder 的对象,用于解析配置文件
2,会创建一个解析xml配置类的一个构造器,会解析xmlconfig里面的全部标签,并保存在configuration里面
3,会创建一个解析xml映射类的一个构造器,专门解析对应mapper.xml里面的全部标签
4,在解析mapper.xml的时候会将里面增删改查的元素全部解析出来,存在一个MapperStatement里面
5,所有的信息解析完之后,都会生成在一个configuration对象,所有的信息都会加入到这个configuration里面
6,最后会创建一个SqlSessionFactory,会将所有的配置信息,都加入到这个SqlSessionFactory里面

发表评论

表情:
评论列表 (有 0 条评论,119人围观)

还没有评论,来说两句吧...

相关阅读