原文网址:Mybatis-Plus--解决自动填充无效的问题-CSDN博客
简介
本文介绍Mybatis-Plus解决自动填充无效的问题。
问题描述
mybatis-plus方法里,如果入参有entity实体,都能自动填充字段。
如果入参没有entity实体,有的能自动填充,有的不能自动填充。
可以自动填充的场景:
userService.removeById(id);
userService.removeBatchByIds(idList);
不能自动填充的场景:
userService.lambdaUpdate()
.eq(User::getUserName, username)
.remove();
解决方法
解析SQL,自动添加SET语句。
package com.example.demo.config.mybatis; import com.baomidou.mybatisplus.core.toolkit.PluginUtils; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.*; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.springframework.stereotype.Component; import java.sql.Connection; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @Intercepts({@Signature( type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class} )}) @Component public class MybatisFillUpdateSqlInterceptor implements Interceptor { // 定义正则表达式用于提取 SET 部分的字段名 private static final Pattern SET_PATTERN = Pattern.compile("UPDATE\\s+[^\\s]+\\s+(SET)"); @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget()); MetaObject metaObject = SystemMetaObject.forObject(statementHandler); MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement"); if (SqlCommandType.UPDATE == mappedStatement.getSqlCommandType() && StatementType.CALLABLE != mappedStatement.getStatementType()) { BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql"); // 获取已经构造好的SQL String sql = boundSql.getSql(); // 获取映射的参数 List<ParameterMapping> mappings = new ArrayList(boundSql.getParameterMappings()); // 假如参数中不包含要构造的参数,手动写入 Map<String, String> fieldsMap = customFieldMap(); for (Entry<String, String> map : fieldsMap.entrySet()) { String fieldKey = map.getKey(); Matcher setMatcher = SET_PATTERN.matcher(sql); // 找到UPDATE才处理 if (setMatcher.find()) { Pattern fieldPattern = Pattern.compile("UPDATE\\s+[^\\s]+\\s+(SET)\\s+[^\\s]*" + fieldKey + "=" + "[^\\s]+"); Matcher fieldMatcher = fieldPattern.matcher(sql); if (!fieldMatcher.find()) { // 原SQL有此字段,则不处理 int indexOfSet = setMatcher.start(1);; String sqlPart = fieldKey + "='" + map.getValue() + "', "; sql = sql.substring(0, indexOfSet) + " SET " + sqlPart + sql.substring(indexOfSet + 4); } } } metaObject.setValue("delegate.boundSql.sql", sql); metaObject.setValue("delegate.boundSql.parameterMappings", mappings); } return invocation.proceed(); } @Override public Object plugin(Object target) { return target instanceof StatementHandler ? Plugin.wrap(target, this) : target; } private Map<String, String> customFieldMap() { Map<String, String> params = new HashMap<>(); String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); params.put("update_time", now); return params; } }