连接MyBatis内部SqlSession与业务接口的代理类MapperProxy
2019獨角獸企業重金招聘Python工程師標準>>>
目的
系統中的業務接口需要調用MyBatis的SQL時,業務接口定義的參數不符合MyBatis自己內部的規范,那么就需要把業務接口的參數轉換成MyBatis內部參數規,MapperProxy代理就完成了這一職責,下面就來分析一下。
public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{if?(Object.class.equals(method.getDeclaringClass()))?{try?{return?method.invoke(this,?args);}?catch?(Throwable?t)?{throw?ExceptionUtil.unwrapThrowable(t);}}final?MapperMethod?mapperMethod?=?cachedMapperMethod(method);return?mapperMethod.execute(sqlSession,?args); }private?MapperMethod?cachedMapperMethod(Method?method)?{MapperMethod?mapperMethod?=?methodCache.get(method);if?(mapperMethod?==?null)?{mapperMethod?=?new?MapperMethod(mapperInterface,?method,?sqlSession.getConfiguration());methodCache.put(method,?mapperMethod);}return?mapperMethod; }上面的invoke就是代理類回調的方法,而cachedMapperMethod方法,做了一個緩存。這里MapperMethod類的構造器與MapperMethod類的execute方法就是主要的邏輯,先來看一下MapperMethod構造器。
1?MapperMethod構造器
這里有2個類的實例化,根據圖中的查詢分析一下這2個類。
public?SqlCommand(Configuration?configuration,?Class<?>?mapperInterface,?Method?method)?throws?BindingException?{//?cn.vansky.schedule.time.menu.dao.MenuMapper.findMenuByUserIdString?statementName?=?mapperInterface.getName()?+?"."?+?method.getName();MappedStatement?ms?=?null;if?(configuration.hasStatement(statementName))?{ms?=?configuration.getMappedStatement(statementName);}?else?if?(!mapperInterface.equals(method.getDeclaringClass().getName()))?{?//?issue?#35String?parentStatementName?=?method.getDeclaringClass().getName()?+?"."?+?method.getName();if?(configuration.hasStatement(parentStatementName))?{ms?=?configuration.getMappedStatement(parentStatementName);}}if?(ms?==?null)?{throw?new?BindingException("Invalid?bound?statement?(not?found):?"?+?statementName);}//?cn.vansky.schedule.time.menu.dao.MenuMapper.findMenuByUserIdname?=?ms.getId();//?SELECTtype?=?ms.getSqlCommandType();if?(type?==?SqlCommandType.UNKNOWN)?{throw?new?BindingException("Unknown?execution?method?for:?"?+?name);} }public?MethodSignature(Configuration?configuration,?Method?method)?throws?BindingException?{//?返回值類型Class//?interface?java.util.Listthis.returnType?=?method.getReturnType();//?有無返回值?true:無,false:有//?falsethis.returnsVoid?=?void.class.equals(this.returnType);//?返回類型是否是集合Collection或者是數組//?truethis.returnsMany?=?(configuration.getObjectFactory().isCollection(this.returnType)?||?this.returnType.isArray());//?返回類型是Map,獲取注解MapKey//?以上方法調用,值為nullthis.mapKey?=?getMapKey(method);//?返回類型是否Map//?falsethis.returnsMap?=?(this.mapKey?!=?null);//?參數是否有@Param注解//?truethis.hasNamedParameters?=?hasNamedParams(method);//?nullthis.rowBoundsIndex?=?getUniqueParamIndex(method,?RowBounds.class);//?nullthis.resultHandlerIndex?=?getUniqueParamIndex(method,?ResultHandler.class);//?獲取參數列表//?0?->?userId?this.params?=?Collections.unmodifiableSortedMap(getParams(method,?this.hasNamedParameters)); }SqlCommand類獲取處理的唯一標識及SQL語句類型,MethodSignature類對業務接口方法的入參類型及出參類型進行處理。
2?MapperMethed執行入口-->execute方法
public?Object?execute(SqlSession?sqlSession,?Object[]?args)?{Object?result;if?(SqlCommandType.INSERT?==?command.getType())?{//?新增Object?param?=?method.convertArgsToSqlCommandParam(args);result?=?rowCountResult(sqlSession.insert(command.getName(),?param));}?else?if?(SqlCommandType.UPDATE?==?command.getType())?{//?修改Object?param?=?method.convertArgsToSqlCommandParam(args);result?=?rowCountResult(sqlSession.update(command.getName(),?param));}?else?if?(SqlCommandType.DELETE?==?command.getType())?{//?刪除Object?param?=?method.convertArgsToSqlCommandParam(args);result?=?rowCountResult(sqlSession.delete(command.getName(),?param));}?else?if?(SqlCommandType.SELECT?==?command.getType())?{//?查詢if?(method.returnsVoid()?&&?method.hasResultHandler())?{//?無返回值voidexecuteWithResultHandler(sqlSession,?args);result?=?null;}?else?if?(method.returnsMany())?{//?集合Collection或數組result?=?executeForMany(sqlSession,?args);}?else?if?(method.returnsMap())?{//?Mapresult?=?executeForMap(sqlSession,?args);}?else?{//?唯一結果Object?param?=?method.convertArgsToSqlCommandParam(args);result?=?sqlSession.selectOne(command.getName(),?param);}}?else?{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; }增(INSERT)、改(UPDATE)、刪(DELETE),這3種操作可以歸納為一種,首先對業務接口的實際入參轉成MyBatis內部參數,然后調用SqlSession的處理方法,最后對結果進行處理,返回結果。
查(SELECT)有4中情況。
一:無返回值
二:返回是集合Collection或者數組
三:返回是Map
四:返回一個結果
4種情況的具體細節不再分析。
總結
綜上首先需要先把業務接口的實際入參轉成MyBatis內部的參數,然后調用SqlSession相應的處理方法,最后對返回結果進行處理,在返回給業務接口。
轉載于:https://my.oschina.net/u/1269959/blog/524486
總結
以上是生活随笔為你收集整理的连接MyBatis内部SqlSession与业务接口的代理类MapperProxy的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 志存高远,少年当自强
- 下一篇: oracle blob 24909,im