面試官問:Mybatis Plus 是如何實現(xiàn)動態(tài) SQL 語句的?原理你懂嗎?
閱讀本文大概需要 4?分鐘。
來源:juejin.cn/post/6883081187103866894

public?class?MybatisSqlSessionFactoryBuilder?extends?SqlSessionFactoryBuilder?{????public?SqlSessionFactory?build(Configuration?configuration)?{????????????//?...?省略若干行????????????if?(globalConfig.isEnableSqlRunner())?{????????????????new?SqlRunnerInjector().inject(configuration);????????????}????????????//?...?省略若干行????????????return?sqlSessionFactory;????????}}
擴(kuò)展繼承自Mybatis的MybatisConfiguration類: MP動態(tài)腳本構(gòu)建,注冊,及其它邏輯判斷。
SqlRunnerInjector: MP默認(rèn)插入一些動態(tài)方法的xml 腳本方法。
public?class?MybatisConfiguration?extends?Configuration?{????/**?????*?Mapper?注冊?????*/????protected?final?MybatisMapperRegistry?mybatisMapperRegistry?=?new?MybatisMapperRegistry(this);// ....????/**?????*?初始化調(diào)用?????*/????public?MybatisConfiguration()?{????????super();????????this.mapUnderscoreToCamelCase?=?true;????????languageRegistry.setDefaultDriverClass(MybatisXMLLanguageDriver.class);}????/**?????* MybatisPlus 加載 SQL 順序:?????*??1、加載?XML中的?SQL?
?????*??2、加載?SqlProvider?中的?SQL?
?????*??3、XmlSql?與?SqlProvider不能包含相同的?SQL?
?????*?調(diào)整后的 SQL優(yōu)先級:XmlSql > sqlProvider > CurdSql
?????*/????????public?void?addMappedStatement(MappedStatement?ms)?{????????//?...}????//?...?省略若干行????/**?????*?使用自己的?MybatisMapperRegistry?????*/????????public??void?addMapper(Class ?type)?{ ????????mybatisMapperRegistry.addMapper(type);????}????//?....?省略若干行}
public?class?MybatisMapperRegistry?extends?MapperRegistry?{????????public??void?addMapper(Class ?type) ?{????????//?...?省略若干行????????MybatisMapperAnnotationBuilder?parser?=?new?MybatisMapperAnnotationBuilder(config,?type);????????parser.parse();????????//?...?省略若干行????}}
public?class?MybatisMapperAnnotationBuilder?extends?MapperAnnotationBuilder?{????????public?void?parse()?{????????//...?省略若干行????????for?(Method?method?:?type.getMethods())?{????????????/**?for循環(huán)代碼,?MP判斷method方法是否是@Select?@Insert等mybatis注解方法**/????????????parseStatement(method);????????????InterceptorIgnoreHelper.initSqlParserInfoCache(cache,?mapperName,?method);????????????SqlParserHelper.initSqlParserInfoCache(mapperName,?method);????????}????????/**?這2行代碼,?MP注入默認(rèn)的方法列表**/????????if?(GlobalConfigUtils.isSupperMapperChildren(configuration,?type))?{????????????GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant,?type);????????}????????//...?省略若干行}????????public?void?inspectInject(MapperBuilderAssistant?builderAssistant,?Class>?mapperClass)?{????????Class>?modelClass?=?extractModelClass(mapperClass);????????//...?省略若干行????????List?methodList?=?this.getMethodList(mapperClass); ????????TableInfo?tableInfo?=?TableInfoHelper.initTableInfo(builderAssistant,?modelClass);????????//?循環(huán)注入自定義方法????????methodList.forEach(m?->?m.inject(builderAssistant,?mapperClass,?modelClass,?tableInfo));????????mapperRegistryCache.add(className);????}}public class DefaultSqlInjector extends AbstractSqlInjector {????????public?List?getMethodList(Class>?mapperClass)? {????????return?Stream.of(????????????new?Insert(),????????????//...?省略若干行????????????new?SelectPage()????????).collect(toList());????}}
/**?*?根據(jù)ID?查詢一條數(shù)據(jù)?*/public?class?SelectById?extends?AbstractMethod?{????????public?MappedStatement?injectMappedStatement(Class>?mapperClass,?Class>?modelClass,?TableInfo?tableInfo)?{????????/**?定義?mybatis?xml?method?id,?對應(yīng)??**/ SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID;????????/**?構(gòu)造id對應(yīng)的具體xml片段?**/????????SqlSource?sqlSource?=?new?RawSqlSource(configuration,?String.format(sqlMethod.getSql(),????????????sqlSelectColumns(tableInfo,?false),????????????tableInfo.getTableName(),?tableInfo.getKeyColumn(),?tableInfo.getKeyProperty(),????????????tableInfo.getLogicDeleteSql(true,?true)),?Object.class);????????/**?將xml?method方法添加到mybatis的MappedStatement中?**/????????return?this.addSelectMappedStatementForTable(mapperClass,?getMethod(sqlMethod),?sqlSource,?tableInfo);????}}

public class YourSqlSessionFactoryBean extends SqlSessionFactoryBean implements ApplicationContextAware {????private?Resource[]?mapperLocations;????????????public?void?setMapperLocations(Resource...?mapperLocations)?{????????super.setMapperLocations(mapperLocations);????????/**?存使用mybatis原生定義的mapper?xml文件路徑**/????????this.mapperLocations?=?mapperLocations;}????/**?????*?{@inheritDoc}?????*/????????public?void?afterPropertiesSet()?throws?Exception?{????????ConfigurableListableBeanFactory?beanFactory?=?getBeanFactory();????????/**?只需要通過將自定義的方法構(gòu)造成xml?resource和原生定義的Resource一起注入到mybatis中即可,?這樣就可以實現(xiàn)MP的自定義動態(tài)SQL和原生SQL的共生關(guān)系**/????????this.setMapperLocations(InjectMapper.getMapperResource(this.dbType,?beanFactory,?this.mapperLocations));????????super.afterPropertiesSet();????}}
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
朕已閱?
評論
圖片
表情

