逆水行舟用力撑,一篙松劲退千寻。这篇文章主要讲述mybatis关于ORM的使用以及设计[DaoInterface 转换 Mapper代理对象]相关的知识,希望能为你提供帮助。
第一节中,分析了Mybatis的ORM框架的初始化,这篇来分析SQL执行过程中,对象->
SQL是如何转换的
其中包含两种映射思想
①DAO接口->
Mapper实例
②执行DAO的方法时,参数->
SQL的转换
- DAO接口如何转变成具体可执行SQL的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的?.
看下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来执行。
文章图片
推荐阅读
- 跨app执行bindservice
- Android学习基础部分
- 架构模式中的Active Record和Data Mapper
- SpringBoot添加webapp目录
- Android-自定义View前传-View的三大流程-Layout
- java(Android)跨Module调用对应类方法需求解决方案
- app开发-1
- android仿网易云音乐引导页仿书旗小说Flutter版ViewPager切换爆炸菜单风扇叶片效果等源码
- Android Button四种点击事件和长按事件