• mybatis关于ORM的使用以及设计(二)[DaoInterface 转换 Mapper代理对象]


    第一节中,分析了Mybatis的ORM框架的初始化,这篇来分析SQL执行过程中,对象->SQL是如何转换的

      其中包含两种映射思想

      ①DAO接口->Mapper实例

      ②执行DAO的方法时,参数->SQL的转换

    • DAO接口如何转变成具体可执行SQL的Mapper

       我们在使用mybatis的时候,Mapper会设置命名空间。

    <mapper namespace="org.mybatis.example.mapper.MybatistestMapper">

     Java对象的DAO接口声明如下:

    1 package org.mybatis.example.mapper;
    2 
    3 import java.util.List;
    4 import org.mybatis.example.model.Mybatistest;
    5 
    6 public interface MybatistestMapper {

      从包结构以及命名分析,Dao接口与Mapper有关系(XML 以及Mapper对象)

      在不使用Spring的时候,mybatis通过sqlSession.getMapper(MybatistestMapper.class) 来获得DAO-Mapper代理代理类。

      查看SqlSession的默认实现类DefaultSqlSession.getMapper(),通过configuration得到Mapper

      @Override
      public <T> T getMapper(Class<T> type) {
        return configuration.<T>getMapper(type, this);
      }

      查看Configuration.getMapper

      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        return mapperRegistry.getMapper(type, sqlSession);
      }

      继续查看mapperRegistry.getMapper。可以得到以下信息

      ①创建Mapper的工厂被缓存在knownMappers

       如果工厂不存在,则报错。查看代码,工厂是在XMLMapperBuilder解析Mapper时候添加进去的。

       根据Mapper.xml中的namespace,缓存Factory。有个好处。对获取的DaoMapper需要在配置文件中配置过。限定了使用范围。也避免后期执行时候出错。

       代码可自行查找源码

      ②当缓存中不存在时,则创建动态代理MapperProxyFactory.newInstance

      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null) {
          throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        }
        try {
          return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
          throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
      }

     mapperProxyFactory.newInstance

      @SuppressWarnings("unchecked")
      protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
      }
    
      public T newInstance(SqlSession sqlSession) {
      //代理类中实际执行操作的代码
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }

      通过以上步骤,我们找到了Dao接口的实现(Mapper 实例接口)

    •  当调用一个DAO接口中的方法时,如何找到SQL以及转化为SQL的?.

      通过上面的代码,可以得知实际执行SQL的是mapperProxy 代理类

      看下mapperProxy 的invoke方法

      @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);

      //通过MapperMethod执行
    return mapperMethod.execute(sqlSession, args); }

     查看MapperMethod的execute方法

    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: {
            Object param = method.convertArgsToSqlCommandParam(args);
         //实际找到SqlSession的update方法。command.getName()是Mapper的Id result
    = rowCountResult(sqlSession.update(command.getName(), param)); break; }

      到此为止,我们只是找到了要执行的SQL。由SqlSession来执行。

      

      

      

         

  • 相关阅读:
    Java 日期字符串与日期类型转换
    Android 开发笔记“关闭默认键盘”
    MySql 日期转字符串
    Android 开发笔记“调用.net webservice遇到的问题”
    远程连接MySQL 不允许
    未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值。
    Android 开发笔记“浅谈DDMS视图”
    Android 开发笔记“Eclipse 调试和快捷键”
    Android 开发笔记“程序安装包APK的制作”
    第四周进度条
  • 原文地址:https://www.cnblogs.com/marioS/p/10300413.html
Copyright © 2020-2023  润新知