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

逆水行舟用力撑,一篙松劲退千寻。这篇文章主要讲述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); }

【mybatis关于ORM的使用以及设计[DaoInterface 转换 Mapper代理对象]】通过以上步骤,我们找到了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来执行。
mybatis关于ORM的使用以及设计[DaoInterface 转换 Mapper代理对象]

文章图片









    推荐阅读