映射器代理上执行方法调用时,调用被委派给MapperProxy来处理。
公开课MapperProxy实现了InvocationHandler,可序列化的{ 私人最终SqlSession SqlSession; 私人最终Class mapperInterface; MapperMethod>私人最终Map<方法;methodCache; 公共MapperProxy (SqlSession SqlSession Class MapperMethod> 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 { 私人配置配置; 私人执行人执行人; 私人布尔自动提交; 私人布尔脏; 私人ListList selectList(字符串的声明中,对象参数,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代理实现数据库调用原理