• Mybatis获取代理对象


    • mybatis-config.xml里标签可以放置多个environment,这里可以切换test和develop数据源
    • databaseIdProvider提供多种数据库,在xml映射文件里选择databaseId即可使用对应的数据库
    • Oracle的自增是使用Sequence实现的,若要获取插入数据的主键,在xml映射里写上selectKey标签,select seq.nextval from dual;
    • 哪些地方不能使用占位符?比如分表时表名,orderby,desc
    • @Mapkey("id")指定返回类型为map时,将id作为key

    1. mybatis参数绑定的过程

    我们写一个UserMapper接口,Mybatis会为改接口创建一个MapperProxy对象。

    1.1 MapperRegistry

    在继续之前,先来了解一下MapperRegistry。

    1. MapperRegistry是mapper的注册类,提供了注册一个包下面的所有Mapper接口。内部维护了一个 private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();map以mapper接口类为key,value是接口类对应的代理工厂。
      void addMapper(Class<T> type)方法简单的将type放进knownMappers里面。不过,这里面还有
            MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
            parser.parse();
    

    这样一个解析操作,暂不做分析。
    2. <T> T getMapper(Class<T> type, SqlSession sqlSession)该方法是本类最重要的一个方法了,获取Mapper接口的代理对象也正是从该方法获取的。
    该方法实现就是,knownMappers.get(type)得到代理对象工厂mapperProxyFactory,返回的是mapperProxyFactory.newInstance(sqlSession)
    进入该方法发现过程也比较简单,构造了一个MapperProxy对象

       public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
      }
    

    再进去看

      protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
      }
    

    发现这就是标准的JDK面向接口的动态代理啊。要问对应的InvocationHandler在哪里?mapperProxy就是啦。
    至此,Mybatis如何获取Mapper接口的代理对象已经解决。
    再梳理一下整个流程:

    sqlsession.getMapper->configuration.getMapper->mapperRegistry.getMapper->获取Mapper代理对象

    1.2

    创建好MapperProxy对象之后,调用Mapper.xx方法时就会走MapperProxy的invoke方法

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          if (Object.class.equals(method.getDeclaringClass())) {//如果方法是在Object里面的,放行
            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);//缓存method方法
        return mapperMethod.execute(sqlSession, args); // 执行
      }
    

    发现关键点在于mapperMethod.execute(sqlSession, args)方法

    当你准备好了,机会来临的时候,你才能抓住
  • 相关阅读:
    编译内核开始的小问题Unable to find the Ncurses libraries
    qq for linux Ubuntu 64位兼容
    ubuntu下安装lighttpd
    搭建boa服务器
    INI file and Iniparser
    kernel常用.gitignore配置
    光谱学习
    jump to case label fpermissive
    Qt通用方法及类库5
    Qt通用方法及类库1
  • 原文地址:https://www.cnblogs.com/studentytj/p/10428572.html
Copyright © 2020-2023  润新知