Mapper 接口如何与写 SQL 的 XML 文件进行绑定的?

    科技2026-06-12  4

    Mapper 接口与 XML 文件的绑定是通过 XML 里 mapper 标签的 namespace 值与 Mapper 接口的 包路径.接口名 进行绑定

    Mapper 接口的方法名与 XML 文件中的 sql、select、insert、update、delete 标签的 id 参数值进行绑定

    其中涉及到了 MappedStatement 的 id、SqlCommand 的 name 的值为 Mapper 接口的 包路径.接口名.方法名

     

    源码分析

    要点 1、Mapper 接口与 XML 文件的绑定是通过 XML 里 mapper 标签的 namespace 值与 Mapper 接口的 包路径.接口名 进行绑定

    源码体现在 XMLMapperBuilder 的 bindMapperForNamespace 方法

    private void bindMapperForNamespace() {     String namespace = builderAssistant.getCurrentNamespace();     if (namespace != null) {         Class<?> boundType = null;         try {             boundType = Resources.classForName(namespace);         } catch (ClassNotFoundException e) {             // ignore, bound type is not required         }         if (boundType != null && !configuration.hasMapper(boundType)) {             // Spring may not know the real resource name so we set a flag             // to prevent loading again this resource from the mapper interface             // look at MapperAnnotationBuilder#loadXmlResource             configuration.addLoadedResource("namespace:" + namespace);             configuration.addMapper(boundType);         }     } }

     

     

    要点 2、Mapper 接口的方法名与 XML 文件中的 sql、select、insert、update、delete 标签的 id 参数值进行绑定

    源码体现在两个部分

    1)生成 id 与 MappedStatement 对象注册到 configuration

    XMLMapperBuilder configurationElement 方法中

    //sql标签 sqlElement(context.evalNodes("/mapper/sql")); //select、insert、update、delete标签 buildStatementFromContext(context.evalNodes("select|insert|update|delete"));

     

    XMLMapperBuilder sqlElement 方法中

    String id = context.getStringAttribute("id"); id = builderAssistant.applyCurrentNamespace(id, false); if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {     sqlFragments.put(id, context); }

     

    XMLStatementBuilder parseStatementNode 方法中

    //获取 Mapper xml 中标签 id String id = context.getStringAttribute("id"); builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,     fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,     resultSetTypeEnum, flushCache, useCache, resultOrdered,     keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);

     

    MapperBuilderAssistant addMappedStatement 方法中

    id = applyCurrentNamespace(id, false);

     

    MapperBuilderAssistant applyCurrentNamespace 方法中

    return currentNamespace + "." + base;

     

    MapperBuilderAssistant addMappedStatement 方法中,最后把 MappedStatement 注册到 configuration 对象中

    configuration.addMappedStatement(statement);

     

     

    2)根据 Mapper 接口方法查到并调用对应的 MappedStatement,完成绑定

    MapperProxy cachedInvoker 方法创建 PlainMethodInvoker 对象,创建了 MapperMethod 对象

    return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));

     

    MapperMethod 对象的 SqlCommand 中的 name 属性根据解析设置为对应的 MappedStatement 的 id

    MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,configuration); name = ms.getId();

     

    MapperMethod execute 方法 SqlCommand 类型,通过 sqlSession 根据 SqlCommand 的 name(上一步被设置为 对应的 MappedStatement 的 id) 找到 MappedStatement 执行 select、insert、update、delete

    public Object execute(SqlSession sqlSession, Object[] args) {     Object result;     switch (command.getType()) {       case INSERT: {         Object param = method.convertArgsToSqlCommandParam(args);         result = rowCountResult(sqlSession.insert(command.getName(), param));         break;       }       case UPDATE: {         .         .         .     return result;   } }

     

     


    【Java面试题与答案】整理推荐

    基础与语法集合网络编程并发编程Web安全设计模式框架算法与数据结构异常文件解析与生成LinuxMySQLOracleRedisDubbo

     

    Processed: 0.016, SQL: 9