详解MyBatis Mapper代理实现数据库调用原理

  

  

映射器代理上执行方法调用时,调用被委派给MapperProxy来处理。

        公开课MapperProxy实现了InvocationHandler,可序列化的{   私人最终SqlSession SqlSession;   私人最终ClassmapperInterface;   MapperMethod>私人最终Map<方法;methodCache;      公共MapperProxy (SqlSession SqlSession ClassMapperMethod> mapperInterface Map<方法;methodCache) {   这一点。sqlSession=sqlSession;   这一点。mapperInterface=mapperInterface;   这一点。methodCache=methodCache;   }      公共对象调用对象代理、方法方法,对象[]args)抛出Throwable {   如果(Object.class.equals (method.getDeclaringClass ())) {   尝试{   方法返回。调用(这一点,args);   }捕捉(Throwable t) {   把ExceptionUtil.unwrapThrowable (t);   }   }//接口里声明的方法,转换为MapperMethod来调用   最后MapperMethod MapperMethod=cachedMapperMethod(方法);//与春天集成时此处的sqlSession仍然SqlSessionTemplate   mapperMethod返回。执行(sqlSession, args);   }      私人MapperMethod cachedMapperMethod(方法方法){   MapperMethod MapperMethod=methodCache.get(方法);   如果(mapperMethod==null) {   mapperMethod=new mapperMethod (mapperInterface方法,sqlSession.getConfiguration ());   methodCache。把(方法、mapperMethod);   }   返回mapperMethod;   }   }      之前      

MapperMethod根据mapperInterface.getName () +“。”+ method.getName()从配置对象里找到对应的MappedStatement,从而得到要执行的SQL操作类型(插入/删除/更新/选择/平),然后调用传入的sqlSession实例上的相应的方法。

        公共对象执行(SqlSession SqlSession Object [] args) {   对象的结果;   如果(SqlCommandType。插入==command.getType ()) {//把参数转换为SqlSession能处理的格式   对象参数=method.convertArgsToSqlCommandParam (args);//在sqlSession上执行并处理结果   结果=rowCountResult (sqlSession.insert (command.getName(),参数));   如果(SqlCommandType}其他。更新==command.getType ()) {   对象参数=method.convertArgsToSqlCommandParam (args);   结果=rowCountResult (sqlSession.update (command.getName(),参数));   …省略      之前      

如果上述方法传入的是SqlSessionTemplate,那么这些方法调用会被SqlSessionInterceptor拦截,加入与春天事务管理机制协作的逻辑,具体可以看这篇文章MyBatis事务管理,这里不再展开,最终会调用到DefaultSqlSession实例上的方法。

  


  

  

SqlSession里声明的所有方法的第一个参数如果是字符串的声明,则都是mapperInterface.getName () +“。”+ method.getName()表示要调用的SQL语句的标识符。通过它从配置找到MappedStatement。

  

会话层最主要的逻辑是进行参数的包装,获取对应的MappedStatement,然后调用持有的遗嘱执行人的方法去执行。

        公共类DefaultSqlSession实现SqlSession {   私人配置配置;   私人执行人执行人;      私人布尔自动提交;   私人布尔脏;   私人ListListselectList(字符串的声明中,对象参数,RowBounds RowBounds) {   尝试{   MappedStatement=configuration.getMappedStatement女士(声明);   返回执行人。查询(ms, wrapCollection(参数),rowBounds, Executor.NO_RESULT_HANDLER);   }捕捉(异常e) {   把ExceptionFactory。wrapException(“错误查询数据库。原因:”+ e, e);   最后}{   .reset ErrorContext.instance () ();   }   }      之前      


  

  

我们知道JDBC里有三种数据库语句:java.sql。声明/PreparedStatement/CallableStatement,每种语句的执行方式是不一样的,MyBatis创建了StatementHandler抽象来表示数据库语句的处理逻辑,有对应的三种具体实现:SimpleStatementHandler/PreparedStatementHandler/CallableStatementHandler。

  

RoutingStatementHandler是个门面模式,构建时根据要执行的数据库语句类型实例化SimpleStatementHandler/PreparedStatementHandler CallableStatementHandler中的一个类作为目标委托,并把调用都转给这个委托的方法。

  

不同的处理程序实现实现了对应的:数据库语句的创建,参数化设置,执行语句。

详解MyBatis Mapper代理实现数据库调用原理