metaObjectHandler.insertFill会调用上面自己定义的MyMetaObjectHandler的insertFill方法,然后会继续调用strictInsertFill方法 。
分析下strictInsertFill方法如下:
MetaObjectHandler
default MetaObjectHandler strictInsertFill(TableInfo tableInfo, MetaObject metaObject, List<StrictFill<?, ?>> strictFills) {return strictFill(true, tableInfo, metaObject, strictFills);}/*** 严格填充,只针对非主键的字段,只有该表注解了fill 并且 字段名和字段属性 能匹配到才会进行填充(null 值不填充)** @param insertFill是否验证在 insert 时填充* @param tableInfocache 缓存* @param metaObjectmetaObject meta object parameter* @param strictFills 填充信息* @return this* @since 3.3.0*/default MetaObjectHandler strictFill(boolean insertFill, TableInfo tableInfo, MetaObject metaObject, List<StrictFill<?, ?>> strictFills) {// 先过滤表上withInsertFill或withUpdateFill属性是否为true,其实就是看dao层对应的类属性上是否有// @TableField(fill = FieldFill.INSERT)或@TableField(fill = FieldFill.UPDATE)注解if ((insertFill && tableInfo.isWithInsertFill()) || (!insertFill && tableInfo.isWithUpdateFill())) {strictFills.forEach(i -> {final String fieldName = i.getFieldName();final Class<?> fieldType = i.getFieldType();tableInfo.getFieldList().stream()// 过滤对象字段,把字段上有@TableField(fill = FieldFill.INSERT)或@TableField(fill = FieldFill.UPDATE)注解// 的字段过滤出来 。.filter(j -> j.getProperty().equals(fieldName) && fieldType.equals(j.getPropertyType()) &&((insertFill && j.isWithInsertFill()) || (!insertFill && j.isWithUpdateFill()))).findFirst()// 针对过滤出来的字段赋值 。.ifPresent(j -> strictFillStrategy(metaObject, fieldName, i.getFieldVal()));});}return this;}上面分析完了MybatisParameterHandler处理字段自动填充流程的核心逻辑,是从它的方法process说起的,那这个方法又是怎么被触发的?怎么和mybaties执行流程对接上的?
下面是mybaties 查询方法完成的调用时序图

文章插图
上面重点关注下MybatisParameterHandler类的方法,主要两步:
- 在执行器进行具体jdbc操作前,先初始化了StatementHandler,StatementHandler里面会创建MybatisParameterHandler,在MybatisParameterHandler的构造方法中最终会调用process方法,进而为对象进行字段填充操作 。
- 在prepareStatement阶段,jdbc执行prepare操作完成后会返回一个Statement,StatementHandler会调用MybatisParameterHandler的setParameters方法,解析dao层对象属性,并把参数值设置到prepare返回的Statement中 。
mybatis plus 基本的增删改查为什么不用写sql?以及sql注入器的原理 。mybatis plus通过定义sql注入器实现了此功能 。核心类
DefaultSqlInjector
@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {Stream.Builder<AbstractMethod> builder = Stream.<AbstractMethod>builder()// 注入BaseMapper的insert方法.add(new Insert())// 注入BaseMapper的delete方法.add(new Delete()).add(new DeleteByMap()).add(new Update()).add(new SelectByMap()).add(new SelectCount()).add(new SelectMaps()).add(new SelectMapsPage()).add(new SelectObjs())// 注入BaseMapper的selectList方法.add(new SelectList()).add(new SelectPage());if (tableInfo.havePK()) {builder.add(new DeleteById()).add(new DeleteBatchByIds()).add(new UpdateById()).add(new SelectById()).add(new SelectBatchByIds());} else {logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.",tableInfo.getEntityType()));}return builder.build().collect(toList());}这里以insert举例看下Insert内部实现 。Insert
/** * 插入一条数据(选择字段插入) * * @author hubin * @since 2018-04-06 */public class Insert extends AbstractMethod {public Insert() {super(SqlMethod.INSERT_ONE.getMethod());}/*** @param name 方法名* @since 3.5.0*/public Insert(String name) {super(name);}@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;// INSERT_ONE("insert", "插入一条数据(选择字段插入)", "<script>nINSERT INTO %s %s VALUES %sn</script>")// INSERT_ONE枚举里面定义了sql脚本,以及BaseMapper中对应方法名SqlMethod sqlMethod = SqlMethod.INSERT_ONE;// 通过dao类对应表信息,获取表中的列并且拼“接插入sql”的列部分String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(null),LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);// 通过dao类对应表信息,获取表中的列并且拼接“插入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 = Jdbc3KeyGenerator.INSTANCE;keyProperty = tableInfo.getKeyProperty();keyColumn = tableInfo.getKeyColumn();} else if (null != tableInfo.getKeySequence()) {keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, builderAssistant);keyProperty = tableInfo.getKeyProperty();keyColumn = tableInfo.getKeyColumn();}}// 通过上面获取的插入sql脚本,以及列和值部分,拼接成最终的sql脚本字符串 。String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);// 通过上面的信息生成对应的MapperStatement,并且注册到mybaties容器中 。供后续真正调用BaseMapper对应方法// 的时候再取出来使用 。return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 李小璐|离婚后彻底放飞自我,璐的审美,真是多年如一日的稳定!
- 秦海璐|秦海璐彻底告别大妈形象,蓝色紧身牛仔裤搭白色卫衣,女人味十足!
- 什么原因无法彻底治理沙尘暴
- 黄晓明|离婚早有征兆,杨颖想复合却被拒绝,黄晓明表示想彻底放下
- 湿疹怎么才能根除(怎么做才能彻底治愈湿疹)
- 张翰|他的口碑彻底崩了?
- 徐娇|星女郎徐娇彻底转型:开公司学设计,还连续8年推广汉服
- 张庭|张庭夫妇彻底凉了,前妻儿子发文说“开心”
- 赵丽颖|穿汉服最好看的几位明星:刘诗诗白鹿气质佳,看到赵丽颖彻底惊艳
- 章子怡|张艺谋40岁长女彻底翻身!穿红裙走红毯独当一面,红唇卷发撞脸章子怡
