Mybatis源码解析【Mapper文件解析】

1、解析过程中,一些重要的类,如下:

1、XMLMapperBuilder,一个mapper文件一个builder
2、MapperBuilderAssistant,XMLMapperBuilder的助手
3、Cache,缓存对象
4、XMLStatementBuilder,一条SQL一个MapperStatement
5、KeyGenerator,主键生成策略
6、XMLScriptBuilder,SQL内容解析Builder
7、DynamicSqlSource,具有动态标签的SQL;RawSqlSource,不具有动态标签的SQL
8、GenericTokenParser,占位符解析${},#{}

2、入口看到XMLConfigBuilder.parseConfiguration(),解析Mybatis配置文件中的标签

  private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

3、next,看到mapperElement()方法,进入到方法里,可以看到有几种解析mapper标签的方式(url,resource,mapperClass)

4、重点看XMLMapperBuilder中的parse()方法,看到了builderAssistant助手,只是为了记录信息,方便在其它地方能获取到当前mapper的信息,比如说namespace,mapperstatement等等

  private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      //  记录名称空间
      builderAssistant.setCurrentNamespace(namespace);
      //  当前名称空间是否和其它namespace使用同一个缓存
      cacheRefElement(context.evalNode("cache-ref"));
      //  当前mapper是否开启缓存  使用namespace作为cacheId
      cacheElement(context.evalNode("cache"));
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      sqlElement(context.evalNodes("/mapper/sql"));
      //  sql解析
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }

5、如果mapper.xml中有cache-ref或者cache,就会用到Mybatis中的二级缓存,这个另外再说,因为缓存又是一个模块。next,重点还是看buildStatementFromContext(),解析curd

6、点进去,就能看到XMLStatementBuilder了,Mybatis在解析中大量使用建造者模式,可能是因为属性比较多,用set方式太鸡肋;顾名思义,XMLStatementBuilder就是构建MapperStatement

7、看到XMLStatementBuilder中的parseStatementNode(),这个就是解析sql标签的方法,这里主要看SqlSource的解析:createSqlSource

  public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
    XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
    return builder.parseScriptNode();
  }

8、XMLScriptBuilder,sql内容解析的builder;DynamicSqlSource和RawSqlSource都实现了SqlSource

  public SqlSource parseScriptNode() {
    // 解析动态标签
    MixedSqlNode rootSqlNode = parseDynamicTags(context);
    SqlSource sqlSource = null;
    if (isDynamic) {
      //  sql中是否有动态标签  if  where foreach ...
      sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
    } else {
      //  没有动态标签
      sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
    }
    return sqlSource;
  }

9、parseDynamicTags,动态标签解析,里面可以看到不同的动态标签会有不同的handler,分别处理,最后解析成SqlNode添加到容器里,解析表达式会用到Ognl

10、上面是大概的mapper文件解析内容,最后说说主键生成策略KeyGenerator,是一个接口,里面有两个方法,

  // 针对Sequence主键而言,在执行insert sql前必须指定一个主键值给要插入的记录
  void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

  // 针对自增主键的表,在插入时不需要主键,而是在插入过程自动获取一个自增的主键
  void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis是一个轻量级的Java持久层开源框架,它封装了JDBC操作数据库的底层细节,提供了一个简单易用的数据库访问方式。 Mybatis源码分为核心模块和附加模块两部分,核心模块主要包括配置解析、SQL解析、SQL执行等功能,附加模块包括连接池、缓存、事务管理等功能。 在Mybatis源码中,配置解析是其中的关键部分。通过解析mybatis-config.xml配置文件,可以获取到数据库连接信息、映射器配置、插件配置等。在配置解析过程中,Mybatis会对配置文件进行校验,确保配置的正确性。 SQL解析Mybatis的另一个重要功能。Mybatis通过解析Mapper接口中的注解或XML配置文件中的SQL语句,将SQL语句解析为ParameterMapping、BoundSql等对象,并将其封装成一个MappedStatement对象,供后续的SQL执行使用。 SQL执行是Mybatis的核心功能之一。在SQL执行阶段,Mybatis会根据MappedStatement中的信息,获取数据库连接,并执行对应的SQL语句。在执行过程中,Mybatis会通过TypeHandler对参数进行类型转换,并使用ResultSetHandler将查询结果封装成Java对象。 除了核心模块,Mybatis源码还包括了连接池、缓存、事务管理等附加模块的实现。连接池模块负责管理数据库连接的获取和释放,缓存模块负责缓存查询结果以提高性能,而事务管理模块则负责管理数据库的事务处理。 总之,Mybatis源码解析涉及多个关键模块的实现,包括配置解析、SQL解析、SQL执行、连接池、缓存、事务管理等。通过了解这些模块的实现原理,我们可以更好地理解和使用Mybatis框架。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值