mybatis mapper 实现

mybatis 可以通过动态代理实现mapper。其中Mapper类和Mapper.xml必须要放在一起。

sqlMapConfig.xml的配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<!-- 别名 包以其子包下所有类   头字母大小都行-->

<!-- 和spring整合后 environments配置将废除    -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}" />
<property name="url"
value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>

<!-- Mapper的位置  Mapper.xml 写Sql语句的文件的位置 -->
<mappers>
<!-- <mapper resource="sqlmap/User.xml" class="" url=""/> -->
<!-- <mapper resource="sqlmap/User.xml" class="" url=""/> -->
<!-- <mapper class="com.itheima.mybatis.mapper.UserMapper" /> -->
<!-- <mapper url="" /> -->
<package name="com.mapper"/>
</mappers>

</configuration>

其中mapper.xml 配置在类的所在目录。

其中解析文件时有这样的代码

  private void loadXmlResource() {
    // Spring may not know the real resource name so we check a flag
    // to prevent loading again a resource twice

    // this flag is set at XMLMapperBuilder#bindMapperForNamespace

   //type.getName()的值为 com.mapper.TestMapper

    if (!configuration.isResourceLoaded("namespace:" + type.getName())) {

//      xmlResource  的值为 com/mapper/TestMapper.xml

String xmlResource = type.getName().replace('.', '/') + ".xml";

      InputStream inputStream = null;
      try {
        inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
      } catch (IOException e) {
        // ignore, resource is not required
      }
      if (inputStream != null) {
        XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
        xmlParser.parse();
      }
    }
  }


执行操作时进入的源代码:

//proxy 是代理生成的类   method 调用的方法  args参数 

@Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args); 
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);

  }


  private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,

        Class<?> declaringClass, Configuration configuration) {

//获取mapper.xml中id  可以看出来 通过 接口类的名称 + 方法名 和参数无关   所以mapper 里面的方法 不能重载

//如果重载了 在解析配置文件时 就会报  Mapped Statements collection already contains value for 、com.mapper.TestMapper.deleteByPrimaryKey 错误信息。




      String statementId = mapperInterface.getName() + "." + methodName;
      if (configuration.hasStatement(statementId)) {
        return configuration.getMappedStatement(statementId);
      } else if (mapperInterface.equals(declaringClass)) {
        return null;
      }
      for (Class<?> superInterface : mapperInterface.getInterfaces()) {
        if (declaringClass.isAssignableFrom(superInterface)) {
          MappedStatement ms = resolveMappedStatement(superInterface, methodName,
              declaringClass, configuration);
          if (ms != null) {
            return ms;
          }
        }
      }
      return null;
    }
  }

猜你喜欢

转载自blog.csdn.net/hyhanyu/article/details/79612232