欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

mybatis接口式编程 调用接口得到数据

程序员文章站 2022-10-03 13:59:21
首先需要知道代理设计模式。mapper只是个接口,并没有能力实现方法。当调用mapper接口,最终的调用的方法是由MapperProxy代理实现类中invoke方法实现的。public class MapperProxy implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; private final S...

首先需要知道代理设计模式。
mapper只是个接口,并没有能力实现方法。
当调用mapper接口,最终的调用的方法是由MapperProxy代理实现类中invoke方法实现的。

public class MapperProxy<T> implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; private final SqlSession sqlSession; private final Class<T> mapperInterface; private final Map<Method, MapperMethod> methodCache; public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; this.methodCache = methodCache; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果调用的方法的所在类是Object if (Object.class.equals(method.getDeclaringClass())) { try { return method.invoke(this, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } //相当于一个map,key:拦截方法对应对的sql,value:相当于组装的一段jdbc的代码 final MapperMethod mapperMethod = cachedMapperMethod(method); // return mapperMethod.execute(sqlSession, args); } private MapperMethod cachedMapperMethod(Method method) { //先从缓存map中取 MapperMethod mapperMethod = methodCache.get(method); if (mapperMethod == null) { //SqlCommand command; //MethodSignature method; mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()); methodCache.put(method, mapperMethod); } return mapperMethod; } } 

其中很明显的可以看到需要先生成MapperMethod,MapperMethod有两个字段分别是SqlCommand command; final MethodSignature method

  • SqlCommand command
    其中又有两个字段String name(mapper中namespace+Sql的id); SqlCommandType type(Sql语句的类型,UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH;)
  • MethodSignature method
    存放于这条sql语句组装的所对应的jdbc代码。
    接下来看看execute方法。先判断是什么类型的sql语句
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); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } case DELETE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } case SELECT: //返回的是否是void,方法中是否含有结果映射 if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; //是否返回多个值 } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else if (method.returnsCursor()) { result = executeForCursor(sqlSession, args); } else { //返回简单数据 //做一个转换,将Java中的参数转换成符合sql的参数类型 Object param = method.convertArgsToSqlCommandParam(args); //调用sqlsession执行。其他的几个也是通过一些设置,最终还是通过调用sqlSession中的方法来执行 result = sqlSession.selectOne(command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; } 
@Override public <T> T selectOne(String statement, Object parameter) { // Popular vote was to return null on 0 results and throw exception on too many. List<T> list = this.<T>selectList(statement, parameter); if (list.size() == 1) { return list.get(0); } else if (list.size() > 1) { throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size()); } else { return null; } } 

selectOne方法其实是通过selectList查询最终取得第一条数据。

@Override public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { //statement就是command.getName(),mapper.xml中namespace+Sql的id获取MappedStatement  //MappedStatement是与之对应的JDBC的代码组成,属性成员比较多 MappedStatement ms = configuration.getMappedStatement(statement); //最终调用四大神器的执行器 执行代码 return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } 

最后代码运行到执行器,开始到Jdbc的调用流程。接下来看看执行器的相关流程
执行器

本文地址:https://blog.csdn.net/wsdfym/article/details/107895864

相关标签: Mybatis 接口