Java数据持久层 (16)

可以说,90%的小伙伴,都是冲着Mybatis-Plus基础mapper不用写的特点,入坑的。
那么Mybatis-Plus,是如何基于Mybatis,实现基础通用mapper呢?
答案,就是继承&覆写,Mybatis的MapperAnnotationBuilder。
Mybatis的MapperAnnotationBuilder,原先是为了提供对@Select等注解的解析。Mybatis-Plus通过继承&重写其中的parse方法,实现了Mybatis-Plus自身通用Mapper的注入。

在这里插入图片描述


有关MapperRegistry之前的流程,详见前文对Mybatis初始化流程中,mapper注入的部分。

MybatisMapperAnnotationBuilder /** * 继承 * 只重写了 {@link MapperAnnotationBuilder#parse} 和 #getReturnType * 没有XML配置文件注入基础CRUD方法 * @author Caratacus * @since 2017-01-04 */ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder { @Override public void parse() { String resource = type.toString(); if (!configuration.isResourceLoaded(resource)) { loadXmlResource(); configuration.addLoadedResource(resource); String mapperName = type.getName(); assistant.setCurrentNamespace(mapperName); parseCache(); parseCacheRef(); InterceptorIgnoreHelper.InterceptorIgnoreCache cache = InterceptorIgnoreHelper.initSqlParserInfoCache(type); for (Method method : type.getMethods()) { if (!canHaveStatement(method)) { continue; } if (getAnnotationWrapper(method, false, Select.class, SelectProvider.class).isPresent() && method.getAnnotation(ResultMap.class) == null) { parseResultMap(method); } try { InterceptorIgnoreHelper.initSqlParserInfoCache(cache, mapperName, method); SqlParserHelper.initSqlParserInfoCache(mapperName, method); parseStatement(method); } catch (IncompleteElementException e) { configuration.addIncompleteMethod(new MybatisMethodResolver(this, method)); } } try { if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) { parserInjector(); } } catch (IncompleteElementException e) { configuration.addIncompleteMethod(new InjectorResolver(this)); } } parsePendingMethods(); } // 核心方法。进行定制化的通用mapper注入 void parserInjector() { GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type); } // 其他方法(略) } Insert

Mybatis-Plus下BaseMapper的通用Mapper方法,实现都在com.baomidou.mybatisplus.core.injector.methods下。
这里,就以Insert为例,简单解析一下。

/** * 插入一条数据(选择字段插入) * * @author hubin * @since 2018-04-06 */ @SuppressWarnings("serial") public class Insert extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { KeyGenerator keyGenerator = new NoKeyGenerator(); SqlMethod sqlMethod = SqlMethod.INSERT_ONE; // 构建Sql的形参 String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(null), LEFT_BRACKET, RIGHT_BRACKET, null, COMMA); // 构建Sql的实参 String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf(null), LEFT_BRACKET, RIGHT_BRACKET, null, COMMA); String keyProperty = null; String keyColumn = null; // 表包含主键处理逻辑,如果不包含主键当普通字段处理 if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) { if (tableInfo.getIdType() == IdType.AUTO) { /** 自增主键 */ keyGenerator = new Jdbc3KeyGenerator(); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } else { if (null != tableInfo.getKeySequence()) { keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } } } // 按照格式要求,配合MethodType,构建对应的sql语句 String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript); // 获取对应SqlSource SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); // 通过AbstractMethod,添加MappedStatement到Mybatis容器-Configuration下Mapper容器:MapperRegistry return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn); } } b.lambda表达式

有关Mybatis-Plus的lambda表达式的实现,涉及的点比较多。这里给一些建议:首先对函数式编程&流式编程有足够的了解,其次需要对wrapper的使用有一定认识,最后剖析Mybatis-Plus中对应部分。

具体实现,详见:
com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
com.baomidou.mybatisplus.core.toolkit.LambdaUtils
com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda

com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper
com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper

最后,愿与诸君共进步。

五、附录 补充

driver加载:jdbc下的driver加载分为三种方式:

driverManager会在第一次调用时,会通过loadInitialDrivers()静态方法,对系统变量中的jdbc.drivers进行驱动注册

直接调用driverManager的register()方法,进行注册。

具体驱动,在初始化时,会调用driverManager的register()方法,进行注册。例:Class.forName("oracle.jdbc.driver.OracleDriver");

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfjfp.html