/** * Copyright (c) 2011-2014, hubin (jobob@qq.com). * <p> * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.baomidou.mybatisplus.mapper; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.baomidou.mybatisplus.toolkit.CollectionUtils; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; import org.apache.ibatis.executor.keygen.KeyGenerator; import org.apache.ibatis.executor.keygen.NoKeyGenerator; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.mapping.SqlSource; import org.apache.ibatis.mapping.StatementType; import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.scripting.defaults.RawSqlSource; import org.apache.ibatis.session.Configuration; import com.baomidou.mybatisplus.entity.GlobalConfiguration; import com.baomidou.mybatisplus.entity.TableFieldInfo; import com.baomidou.mybatisplus.entity.TableInfo; import com.baomidou.mybatisplus.enums.FieldStrategy; import com.baomidou.mybatisplus.enums.IdType; import com.baomidou.mybatisplus.enums.SqlMethod; import com.baomidou.mybatisplus.toolkit.SqlReservedWords; import com.baomidou.mybatisplus.toolkit.StringUtils; import com.baomidou.mybatisplus.toolkit.TableInfoHelper; /** * <p> * SQL 自动注入器 * </p> * * @author hubin sjy * @Date 2016-09-09 */ public class AutoSqlInjector implements ISqlInjector { private static final Log logger = LogFactory.getLog(AutoSqlInjector.class); protected Configuration configuration; protected LanguageDriver languageDriver; protected MapperBuilderAssistant builderAssistant; /** * CRUD注入后给予标识 注入过后不再注入 * * @param builderAssistant * @param mapperClass */ public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) { String className = mapperClass.toString(); Set<String> mapperRegistryCache = GlobalConfiguration.getMapperRegistryCache(builderAssistant.getConfiguration()); if (!mapperRegistryCache.contains(className)) { inject(builderAssistant, mapperClass); mapperRegistryCache.add(className); } } /** * 注入单点 crudSql */ public void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) { this.configuration = builderAssistant.getConfiguration(); this.builderAssistant = builderAssistant; this.languageDriver = configuration.getDefaultScriptingLanguageInstance(); /* * 驼峰设置 PLUS 配置 > 原始配置 */ GlobalConfiguration globalCache = this.getGlobalConfig(); if (!globalCache.isDbColumnUnderline()) { globalCache.setDbColumnUnderline(configuration.isMapUnderscoreToCamelCase()); } Class<?> modelClass = extractModelClass(mapperClass); if (modelClass != null) { TableInfo table = TableInfoHelper.initTableInfo(builderAssistant, modelClass); injectSql(builderAssistant, mapperClass, modelClass, table); } } /** * <p> * 注入SQL * </p> * * @param builderAssistant * @param mapperClass * @param modelClass * @param table */ protected void injectSql(MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { /** * #148 表信息包含主键,注入主键相关方法 */ if (StringUtils.isNotEmpty(table.getKeyProperty())) { /* 删除 */ this.injectDeleteByIdSql(false, mapperClass, modelClass, table); this.injectDeleteByIdSql(true, mapperClass, modelClass, table); /* 修改 */ this.injectUpdateByIdSql(true, mapperClass, modelClass, table); this.injectUpdateByIdSql(false, mapperClass, modelClass, table); /* 查询 */ this.injectSelectByIdSql(false, mapperClass, modelClass, table); this.injectSelectByIdSql(true, mapperClass, modelClass, table); } else { // 表不包含主键时 给予警告 logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.", modelClass.toString())); } /** * 正常注入无需主键方法 */ /* 插入 */ this.injectInsertOneSql(true, mapperClass, modelClass, table); this.injectInsertOneSql(false, mapperClass, modelClass, table); /* 删除 */ this.injectDeleteSql(mapperClass, modelClass, table); this.injectDeleteByMapSql(mapperClass, table); /* 修改 */ this.injectUpdateSql(mapperClass, modelClass, table); /* 查询 */ this.injectSelectByMapSql(mapperClass, modelClass, table); this.injectSelectOneSql(mapperClass, modelClass, table); this.injectSelectCountSql(mapperClass, modelClass, table); this.injectSelectListSql(SqlMethod.SELECT_LIST, mapperClass, modelClass, table); this.injectSelectListSql(SqlMethod.SELECT_PAGE, mapperClass, modelClass, table); this.injectSelectMapsSql(SqlMethod.SELECT_MAPS, mapperClass, modelClass, table); this.injectSelectMapsSql(SqlMethod.SELECT_MAPS_PAGE, mapperClass, modelClass, table); this.injectSelectObjsSql(SqlMethod.SELECT_OBJS, mapperClass, modelClass, table); /* 自定义方法 */ this.inject(configuration, builderAssistant, mapperClass, modelClass, table); } /** * 自定义方法,注入点(子类需重写该方法) */ public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { // to do nothing } /** * 避免扫描到BaseMapper * * @param mapperClass * @return */ protected Class<?> extractModelClass(Class<?> mapperClass) { if (mapperClass == BaseMapper.class) { logger.warn(" Current Class is BaseMapper "); return null; } else { Type[] types = mapperClass.getGenericInterfaces(); ParameterizedType target = null; for (Type type : types) { if (type instanceof ParameterizedType && BaseMapper.class.isAssignableFrom(mapperClass)) { target = (ParameterizedType) type; break; } } return target == null ? null : (Class<?>) target.getActualTypeArguments()[0]; } } /** * <p> * 注入插入 SQL 语句 * </p> * * @param selective 是否选择插入 * @param mapperClass * @param modelClass * @param table */ protected void injectInsertOneSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { /* * INSERT INTO table <trim prefix="(" suffix=")" suffixOverrides=","> * <if test="xx != null">xx,</if> </trim> <trim prefix="values (" * suffix=")" suffixOverrides=","> <if test="xx != null">#{xx},</if> * </trim> */ KeyGenerator keyGenerator = new NoKeyGenerator(); StringBuilder fieldBuilder = new StringBuilder(); StringBuilder placeholderBuilder = new StringBuilder(); SqlMethod sqlMethod = selective ? SqlMethod.INSERT_ONE : SqlMethod.INSERT_ONE_ALL_COLUMN; fieldBuilder.append("\n<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n"); placeholderBuilder.append("\n<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n"); String keyProperty = null; String keyColumn = null; // 表包含主键处理逻辑,如果不包含主键当普通字段处理 if (StringUtils.isNotEmpty(table.getKeyProperty())) { if (table.getIdType() == IdType.AUTO) { /* 自增主键 */ keyGenerator = new Jdbc3KeyGenerator(); keyProperty = table.getKeyProperty(); keyColumn = table.getKeyColumn(); } else { if (null != table.getKeySequence()) { keyGenerator = TableInfoHelper.genKeyGenerator(table, builderAssistant, sqlMethod.getMethod(), languageDriver); keyProperty = table.getKeyProperty(); keyColumn = table.getKeyColumn(); fieldBuilder.append(table.getKeyColumn()).append(","); placeholderBuilder.append("#{").append(table.getKeyProperty()).append("},"); } else { /* 用户输入自定义ID */ fieldBuilder.append(table.getKeyColumn()).append(","); // 正常自定义主键策略 placeholderBuilder.append("#{").append(table.getKeyProperty()).append("},"); } } } List<TableFieldInfo> fieldList = table.getFieldList(); for (TableFieldInfo fieldInfo : fieldList) { if (selective) { fieldBuilder.append(convertIfTagIgnored(fieldInfo, false)); fieldBuilder.append(fieldInfo.getColumn()).append(","); fieldBuilder.append(convertIfTagIgnored(fieldInfo, true)); placeholderBuilder.append(convertIfTagIgnored(fieldInfo, false)); placeholderBuilder.append("#{").append(fieldInfo.getEl()).append("},"); placeholderBuilder.append(convertIfTagIgnored(fieldInfo, true)); } else { fieldBuilder.append(fieldInfo.getColumn()).append(","); placeholderBuilder.append("#{").append(fieldInfo.getEl()).append("},"); } } fieldBuilder.append("\n</trim>"); placeholderBuilder.append("\n</trim>"); String sql = String.format(sqlMethod.getSql(), table.getTableName(), fieldBuilder.toString(), placeholderBuilder.toString()); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource, keyGenerator, keyProperty, keyColumn); } /** * <p> * 注入 entity 条件删除 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table */ protected void injectDeleteSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.DELETE; String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereEntityWrapper(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource); } /** * <p> * 注入 map 条件删除 SQL 语句 * </p> * * @param mapperClass * @param table */ protected void injectDeleteByMapSql(Class<?> mapperClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.DELETE_BY_MAP; String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereByMap(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class); this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource); } /** * <p> * 注入删除 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table */ protected void injectDeleteByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.DELETE_BY_ID; SqlSource sqlSource; String idStr = table.getKeyColumn(); if (batch) { sqlMethod = SqlMethod.DELETE_BATCH_BY_IDS; StringBuilder ids = new StringBuilder(); ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">"); ids.append("#{item}"); ids.append("\n</foreach>"); idStr = ids.toString(); } String sql = String.format(sqlMethod.getSql(), table.getTableName(), table.getKeyColumn(), idStr); sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource); } /** * <p> * 注入更新 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table */ protected void injectUpdateByIdSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = selective ? SqlMethod.UPDATE_BY_ID : SqlMethod.UPDATE_ALL_COLUMN_BY_ID; String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(selective, table, null), table.getKeyColumn(), table.getKeyProperty()); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource); } /** * <p> * 注入批量更新 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table */ protected void injectUpdateSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.UPDATE; String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(true, table, "et."), sqlWhereEntityWrapper(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource); } /** * <p> * 注入查询 SQL 语句 * </p> * * @param batch 是否为批量插入 * @param mapperClass * @param modelClass * @param table */ protected void injectSelectByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID; SqlSource sqlSource; if (batch) { sqlMethod = SqlMethod.SELECT_BATCH_BY_IDS; StringBuilder ids = new StringBuilder(); ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">"); ids.append("#{item}"); ids.append("\n</foreach>"); sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(), table.getKeyColumn(), ids.toString()), modelClass); } else { sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(), table.getKeyColumn(), table.getKeyProperty()), Object.class); } this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table); } /** * <p> * 注入 map 查询 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table */ protected void injectSelectByMapSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.SELECT_BY_MAP; String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(), sqlWhereByMap(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class); this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table); } /** * <p> * 注入实体查询一条记录 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table */ protected void injectSelectOneSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.SELECT_ONE; String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(), sqlWhere(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table); } /** * <p> * 注入EntityWrapper方式查询记录列表 SQL 语句 * </p> * * @param sqlMethod * @param mapperClass * @param modelClass * @param table */ protected void injectSelectListSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, true), table.getTableName(), sqlWhereEntityWrapper(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table); } /** * <p> * 注入EntityWrapper方式查询记录列表 SQL 语句 * </p> * * @param sqlMethod * @param mapperClass * @param modelClass * @param table */ protected void injectSelectMapsSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, true), table.getTableName(), sqlWhereEntityWrapper(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class, table); } /** * <p> * 注入EntityWrapper方式查询记录列表 SQL 语句 * </p> * * @param sqlMethod * @param mapperClass * @param modelClass * @param table */ protected void injectSelectObjsSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { String sql = String.format(sqlMethod.getSql(), sqlSelectObjsColumns(table), table.getTableName(), sqlWhereEntityWrapper(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Object.class, table); } /** * <p> * 注入EntityWrapper查询总记录数 SQL 语句 * </p> * * @param mapperClass * @param modelClass * @param table 表信息 */ protected void injectSelectCountSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = SqlMethod.SELECT_COUNT; String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereEntityWrapper(table)); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Integer.class, null); } /** * <p> * EntityWrapper方式获取select where * </p> * * @param table 表信息 * @return String */ protected String sqlWhereEntityWrapper(TableInfo table) { StringBuilder where = new StringBuilder("\n<if test=\"ew!=null\">"); where.append("\n<if test=\"ew.entity!=null\">\n<where>"); if (StringUtils.isNotEmpty(table.getKeyProperty())) { where.append("\n<if test=\"ew.entity.").append(table.getKeyProperty()).append("!=null\">\n"); where.append(table.getKeyColumn()).append("=#{ew.entity.").append(table.getKeyProperty()).append("}"); where.append("\n</if>"); } List<TableFieldInfo> fieldList = table.getFieldList(); for (TableFieldInfo fieldInfo : fieldList) { where.append(convertIfTag(fieldInfo, "ew.entity.", false)); where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.entity.").append(fieldInfo.getEl()).append("}"); where.append(convertIfTag(fieldInfo, true)); } where.append("\n</where>\n</if>"); where.append("\n<if test=\"ew.sqlSegment!=null\">\n${ew.sqlSegment}\n</if>"); where.append("\n</if>"); return where.toString(); } /** * <p> * SQL 更新 set 语句 * </p> * * @param selective 是否选择判断 * @param table 表信息 * @param prefix 前缀 * @return */ protected String sqlSet(boolean selective, TableInfo table, String prefix) { StringBuilder set = new StringBuilder(); set.append("<trim prefix=\"SET\" suffixOverrides=\",\">"); List<TableFieldInfo> fieldList = table.getFieldList(); for (TableFieldInfo fieldInfo : fieldList) { if (selective) { set.append(convertIfTag(true, fieldInfo, prefix, false)); set.append(fieldInfo.getColumn()).append("=#{"); if (null != prefix) { set.append(prefix); } set.append(fieldInfo.getEl()).append("},"); set.append(convertIfTag(true, fieldInfo, null, true)); } else { set.append(fieldInfo.getColumn()).append("=#{"); if (null != prefix) { set.append(prefix); } set.append(fieldInfo.getEl()).append("},"); } } set.append("\n</trim>"); return set.toString(); } /** * <p> * 获取需要转义的SQL字段 * </p> * * @param convertStr * @return */ protected String sqlWordConvert(String convertStr) { GlobalConfiguration globalConfig = GlobalConfiguration.getGlobalConfig(configuration); return SqlReservedWords.convert(globalConfig, convertStr); } /** * <p> * SQL 查询所有表字段 * </p> * * @param table * @param entityWrapper 是否为包装类型查询 * @return */ protected String sqlSelectColumns(TableInfo table, boolean entityWrapper) { StringBuilder columns = new StringBuilder(); if (null != table.getResultMap()) { /* * 存在 resultMap 映射返回 */ if (entityWrapper) { columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>"); } columns.append("*"); if (entityWrapper) { columns.append("</otherwise></choose>"); } } else { /* * 普通查询 */ if (entityWrapper) { columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>"); } List<TableFieldInfo> fieldList = table.getFieldList(); int _size = 0; if (null != fieldList) { _size = fieldList.size(); } // 主键处理 if (StringUtils.isNotEmpty(table.getKeyProperty())) { if (table.isKeyRelated()) { columns.append(table.getKeyColumn()).append(" AS ").append(sqlWordConvert(table.getKeyProperty())); } else { columns.append(sqlWordConvert(table.getKeyProperty())); } if (_size >= 1) { // 判断其余字段是否存在 columns.append(","); } } if (_size >= 1) { // 字段处理 int i = 0; Iterator<TableFieldInfo> iterator = fieldList.iterator(); while (iterator.hasNext()) { TableFieldInfo fieldInfo = iterator.next(); // 匹配转换内容 String wordConvert = sqlWordConvert(fieldInfo.getProperty()); if (fieldInfo.getColumn().equals(wordConvert)) { columns.append(wordConvert); } else { // 字段属性不一致 columns.append(fieldInfo.getColumn()); columns.append(" AS ").append(wordConvert); } if (i + 1 < _size) { columns.append(","); } i++; } } if (entityWrapper) { columns.append("</otherwise></choose>"); } } /* * 返回所有查询字段内容 */ return columns.toString(); } /** * <p> * SQL 设置selectObj sqlselect * </p> * * @param table 是否为包装类型查询 * @return */ protected String sqlSelectObjsColumns(TableInfo table) { StringBuilder columns = new StringBuilder(); /* * 普通查询 */ columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>"); // 主键处理 if (StringUtils.isNotEmpty(table.getKeyProperty())) { if (table.isKeyRelated()) { columns.append(table.getKeyColumn()).append(" AS ").append(sqlWordConvert(table.getKeyProperty())); } else { columns.append(sqlWordConvert(table.getKeyProperty())); } } else { // 表字段处理 List<TableFieldInfo> fieldList = table.getFieldList(); if (CollectionUtils.isNotEmpty(fieldList)) { TableFieldInfo fieldInfo = fieldList.get(0); // 匹配转换内容 String wordConvert = sqlWordConvert(fieldInfo.getProperty()); if (fieldInfo.getColumn().equals(wordConvert)) { columns.append(wordConvert); } else { // 字段属性不一致 columns.append(fieldInfo.getColumn()); columns.append(" AS ").append(wordConvert); } } } columns.append("</otherwise></choose>"); return columns.toString(); } /** * <p> * SQL 查询条件 * </p> */ protected String sqlWhere(TableInfo table) { StringBuilder where = new StringBuilder(); where.append("\n<where>"); if (StringUtils.isNotEmpty(table.getKeyProperty())) { where.append("\n<if test=\"ew.").append(table.getKeyProperty()).append("!=null\">\n"); where.append(table.getKeyColumn()).append("=#{ew.").append(table.getKeyProperty()).append("}"); where.append("\n</if>"); } List<TableFieldInfo> fieldList = table.getFieldList(); for (TableFieldInfo fieldInfo : fieldList) { where.append(convertIfTag(fieldInfo, "ew.", false)); where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.").append(fieldInfo.getEl()).append("}"); where.append(convertIfTag(fieldInfo, true)); } where.append("\n</where>"); return where.toString(); } /** * <p> * SQL map 查询条件 * </p> */ protected String sqlWhereByMap(TableInfo table) { StringBuilder where = new StringBuilder(); where.append("\n<if test=\"cm!=null and !cm.isEmpty\">"); where.append("\n<where>"); where.append("\n<foreach collection=\"cm.keys\" item=\"k\" separator=\"AND\">"); where.append("\n<if test=\"cm[k] != null\">"); where.append(SqlReservedWords.convert(getGlobalConfig(), "\n${k}")).append(" = #{cm[${k}]}"); where.append("\n</if>"); where.append("\n</foreach>"); where.append("\n</where>"); where.append("\n</if>"); return where.toString(); } /** * <p> * IF 条件转换方法 * </p> * * @param ignored 允许忽略 * @param fieldInfo 字段信息 * @param prefix 条件前缀 * @param close 是否闭合标签 * @return */ protected String convertIfTag(boolean ignored, TableFieldInfo fieldInfo, String prefix, boolean close) { /* 忽略策略 */ FieldStrategy fieldStrategy = fieldInfo.getFieldStrategy(); if (fieldStrategy == FieldStrategy.IGNORED) { if (ignored) { return ""; } // 查询策略,使用全局策略 fieldStrategy = this.getGlobalConfig().getFieldStrategy(); } // 关闭标签 if (close) { return "</if>"; } /* 前缀处理 */ String property = fieldInfo.getProperty(); if (null != prefix) { property = prefix + property; } // 验证逻辑 if (fieldStrategy == FieldStrategy.NOT_EMPTY) { String propertyType = fieldInfo.getPropertyType(); if (StringUtils.isCharSequence(propertyType)) { return String.format("\n\t<if test=\"%s!=null and %s!=''\">", property, property); } else { return String.format("\n\t<if test=\"%s!=null \">", property); } } else { // FieldStrategy.NOT_NULL return String.format("\n\t<if test=\"%s!=null\">", property); } } protected String convertIfTagIgnored(TableFieldInfo fieldInfo, boolean close) { return convertIfTag(true, fieldInfo, null, close); } protected String convertIfTag(TableFieldInfo fieldInfo, String prefix, boolean close) { return convertIfTag(false, fieldInfo, prefix, close); } protected String convertIfTag(TableFieldInfo fieldInfo, boolean close) { return convertIfTag(fieldInfo, null, close); } /* * 查询 */ public MappedStatement addSelectMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource, Class<?> resultType, TableInfo table) { if (null != table) { String resultMap = table.getResultMap(); if (null != resultMap) { /* 返回 resultMap 映射结果集 */ return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.SELECT, null, resultMap, null, new NoKeyGenerator(), null, null); } } /* 普通查询 */ return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.SELECT, null, null, resultType, new NoKeyGenerator(), null, null); } /* * 插入 */ public MappedStatement addInsertMappedStatement(Class<?> mapperClass, Class<?> modelClass, String id, SqlSource sqlSource, KeyGenerator keyGenerator, String keyProperty, String keyColumn) { return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.INSERT, modelClass, null, Integer.class, keyGenerator, keyProperty, keyColumn); } /* * 删除 */ public MappedStatement addDeleteMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource) { return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.DELETE, null, null, Integer.class, new NoKeyGenerator(), null, null); } /* * 更新 */ public MappedStatement addUpdateMappedStatement(Class<?> mapperClass, Class<?> modelClass, String id, SqlSource sqlSource) { return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.UPDATE, modelClass, null, Integer.class, new NoKeyGenerator(), null, null); } public MappedStatement addMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource, SqlCommandType sqlCommandType, Class<?> parameterClass, String resultMap, Class<?> resultType, KeyGenerator keyGenerator, String keyProperty, String keyColumn) { String statementName = mapperClass.getName() + "." + id; if (configuration.hasStatement(statementName)) { System.err.println("{" + statementName + "} Has been loaded by XML or SqlProvider, ignoring the injection of the SQL."); return null; } /* 缓存逻辑处理 */ boolean isSelect = false; if (sqlCommandType == SqlCommandType.SELECT) { isSelect = true; } return builderAssistant.addMappedStatement(id, sqlSource, StatementType.PREPARED, sqlCommandType, null, null, null, parameterClass, resultMap, resultType, null, !isSelect, isSelect, false, keyGenerator, keyProperty, keyColumn, configuration.getDatabaseId(), languageDriver, null); } // --------------------------------------------------------SqlRunner------------------------------------------------------------ public void injectSqlRunner(Configuration configuration) { this.configuration = configuration; this.languageDriver = configuration.getDefaultScriptingLanguageInstance(); initSelectList(); initSelectObjs(); initInsert(); initUpdate(); initDelete(); initCount(); } /** * 是否已经存在MappedStatement * * @param mappedStatement * @return */ private boolean hasMappedStatement(String mappedStatement) { return configuration.hasStatement(mappedStatement, false); } /** * 创建查询MappedStatement * * @param mappedStatement * @param sqlSource 执行的sqlSource * @param resultType 返回的结果类型 */ @SuppressWarnings("serial") private void createSelectMappedStatement(String mappedStatement, SqlSource sqlSource, final Class<?> resultType) { MappedStatement ms = new MappedStatement.Builder(configuration, mappedStatement, sqlSource, SqlCommandType.SELECT) .resultMaps(new ArrayList<ResultMap>() { { add(new ResultMap.Builder(configuration, "defaultResultMap", resultType, new ArrayList<ResultMapping>(0)) .build()); } }).build(); // 缓存 configuration.addMappedStatement(ms); } /** * 创建一个MappedStatement * * @param mappedStatement * @param sqlSource 执行的sqlSource * @param sqlCommandType 执行的sqlCommandType */ @SuppressWarnings("serial") private void createUpdateMappedStatement(String mappedStatement, SqlSource sqlSource, SqlCommandType sqlCommandType) { MappedStatement ms = new MappedStatement.Builder(configuration, mappedStatement, sqlSource, sqlCommandType).resultMaps( new ArrayList<ResultMap>() { { add(new ResultMap.Builder(configuration, "defaultResultMap", int.class, new ArrayList<ResultMapping>(0)) .build()); } }).build(); // 缓存 configuration.addMappedStatement(ms); } /** * initSelectList */ private void initSelectList() { if (hasMappedStatement(SqlRunner.SELECT_LIST)) { logger.warn("MappedStatement 'SqlRunner.SelectList' Already Exists"); return; } SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class); createSelectMappedStatement(SqlRunner.SELECT_LIST, sqlSource, Map.class); } /** * initSelectObjs */ private void initSelectObjs() { if (hasMappedStatement(SqlRunner.SELECT_OBJS)) { logger.warn("MappedStatement 'SqlRunner.SelectObjs' Already Exists"); return; } SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Object.class); createSelectMappedStatement(SqlRunner.SELECT_OBJS, sqlSource, Object.class); } /** * initCount */ private void initCount() { if (hasMappedStatement(SqlRunner.COUNT)) { logger.warn("MappedStatement 'SqlRunner.Count' Already Exists"); return; } SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class); createSelectMappedStatement(SqlRunner.COUNT, sqlSource, Integer.class); } /** * initInsert */ private void initInsert() { if (hasMappedStatement(SqlRunner.INSERT)) { logger.warn("MappedStatement 'SqlRunner.Insert' Already Exists"); return; } SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class); createUpdateMappedStatement(SqlRunner.INSERT, sqlSource, SqlCommandType.INSERT); } /** * initUpdate */ private void initUpdate() { if (hasMappedStatement(SqlRunner.UPDATE)) { logger.warn("MappedStatement 'SqlRunner.Update' Already Exists"); return; } SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class); createUpdateMappedStatement(SqlRunner.UPDATE, sqlSource, SqlCommandType.UPDATE); } /** * initDelete */ private void initDelete() { if (hasMappedStatement(SqlRunner.DELETE)) { logger.warn("MappedStatement 'SqlRunner.Delete' Already Exists"); return; } SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class); createUpdateMappedStatement(SqlRunner.DELETE, sqlSource, SqlCommandType.DELETE); } /** * <p> * 全局配置 * </p> */ protected GlobalConfiguration getGlobalConfig() { return GlobalConfiguration.getGlobalConfig(configuration); } }