package com.bfkj.unidia.DataBaseUtils; import com.bfkj.unidia.Result; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.sql.ResultSet; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.TimeUnit; import java.util.function.Function; import static com.bfkj.unidia.cacheUtils.CacheUtil.buildCaffeineCache; @Service public class DbExecutor { private static final Logger logger = LoggerFactory.getLogger(DbExecutor.class); private final JdbcExecutor jdbcExecutor; private final TableStructureManager tableStructureManager; private final DbUtils dbUtils; private final DbParamsService dbParamsService; @Autowired public DbExecutor(JdbcExecutor jdbcExecutor, TableStructureManager tableStructureManager, DbUtils dbUtils, DbParamsService dbParamsService) { this.jdbcExecutor = jdbcExecutor; this.tableStructureManager = tableStructureManager; this.dbUtils = dbUtils; this.dbParamsService = dbParamsService; } private final Cache> queryCache = buildCaffeineCache(); /** * 更新数据库记录 * 该方法根据提供的参数和数据库配置,执行相应的数据库操作(插入、更新、删除) * * @param dbConfig 数据库配置信息,包括连接字符串、用户名、密码等 * @param tableName 需要操作的数据库表名 * @param params 操作所需的参数,包括操作类型(INSERT、UPDATE、DELETE)及相应的数据 * @return 返回一个Result对象,包含操作结果,主要是影响的行数 */ public Result dbUpdate(Map dbConfig, String tableName, Map params) { //参数预处理,包括参数校验 (会拼接成完整的sql) Result processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName); //如果参数不合法,返回错误信息 if (!processDataContextResult.isSuccess()) { return Result.fail(processDataContextResult.getError()); } DbParamsService.ProcessedResult dbParams = processDataContextResult.getData(); //依据不同事件进行操作 String event = dbParams.getEvent().toUpperCase(); //根据事件类型执行相应的数据库操作 if(event.equals("INSERT")){//新增 return execInsert(dbConfig, tableName, dbParams); } if(event.equals("UPDATE")){//更新 return execUpdate(dbConfig,dbParams); } if(event.equals("DELETE")){//删除 return execDelete(dbParams, dbConfig); } //如果事件类型不支持,返回错误信息 return Result.fail("不支持的事件类型"); } /** * 更新数据库记录 * 该方法根据提供的参数和数据库配置,执行相应的数据库操作(插入、更新、删除) * * @param dbConfig 数据库配置信息,包括连接字符串、用户名、密码等 * @param tableName 需要操作的数据库表名 * @param params 操作所需的参数,包括操作类型(INSERT、UPDATE、DELETE)及相应的数据 * @return 返回一个Result对象,包含操作结果,主要是影响的行数 */ public Result>> dbUpdateWithFailures(Map dbConfig, String tableName, Map params) { //参数预处理,包括参数校验 (会拼接成完整的sql) Result processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName); //如果参数不合法,返回错误信息 if (!processDataContextResult.isSuccess()) { return Result.fail(processDataContextResult.getError()); } DbParamsService.ProcessedResult dbParams = processDataContextResult.getData(); //依据不同事件进行操作 String event = dbParams.getEvent().toUpperCase(); //根据事件类型执行相应的数据库操作 if(event.equals("INSERT")){//新增 return execInsertWithFailures(dbConfig, tableName, dbParams); } if(event.equals("UPDATE")){//更新 return execUpdateWithFailures(dbConfig,dbParams); } //如果事件类型不支持,返回错误信息 return Result.fail("不支持的事件类型"); } /** * 执行插入操作 * * @param dbConfig 数据库配置信息 * @param tableName 表名 * @param dbParams 数据库参数服务处理结果,包含插入所需的字段和值 * @return 返回插入操作的结果,包括成功或失败及受影响的行数 */ private Result>> execInsertWithFailures(Map dbConfig, String tableName, DbParamsService.ProcessedResult dbParams){ try { // 检查是否存在新增字段,若存在则创建表结构 Map addColumn = dbParams.getAddColumns(); // "c" : value if (!addColumn.isEmpty()) { // 不存在的列数量是否大于0 // 创建表 或者创建字段 Result createTableResult = tableStructureManager.createTable(dbConfig, tableName, addColumn); if (!createTableResult.isSuccess()) { return Result.fail("表创建失败"); } } // 获取插入的列名和对应的值,执行批量插入操作 String insertColumns = dbParams.getInsertColumns(); List> insertParam = dbParams.getInsertValues(); // 占位符对应的value集合 if (!insertParam.isEmpty()) { // 新增 Result>> batchInsert = jdbcExecutor.batchUpdateWithFailures(dbConfig, insertColumns, insertParam); if(!batchInsert.isSuccess()){ return Result.fail(batchInsert.getError()); } return Result.success(batchInsert.getData()); } // 检查是否存在更新条件,若存在则执行更新操作 Map>> queryConditionList = dbParams.getQueryConditions(); if(!queryConditionList.isEmpty()){ Result>> updated = execUpdateWithFailures(dbConfig,dbParams); if(!updated.isSuccess()){ return Result.fail(updated.getError()); } return Result.success(updated.getData()); } // 返回插入操作的结果,包括受影响的行数 return Result.success(null); } catch (Exception e) { logger.error("新增错误", e); return Result.fail("新增错误", e); } } /** * 执行数据库更新操作 * * @param dbConfig 数据库配置信息,包含连接数据库所需的参数 * @param dbParams 处理后的数据库参数对象,包含更新所需的列和查询条件 * @return 返回一个Result对象,包含受影响的行数如果更新操作失败,返回失败的Result对象 */ private Result>> execUpdateWithFailures(Map dbConfig, DbParamsService.ProcessedResult dbParams){ try { // 获取需要更新的列字符串 String updateColumns = dbParams.getUpdateColumns(); List> failedList = null; // 初始化更新计数器 // 遍历查询条件,执行更新操作 for(String queryCondition : dbParams.getQueryConditions().keySet()){ // 获取当前查询条件的参数 List> queryParam = dbParams.getQueryConditions().get(queryCondition); // 拼接更新SQL语句 , sql拼接完成 String updateSql = updateColumns.concat(" where ").concat(queryCondition); // 执行批量更新操作 Result>> batchedUpdate = jdbcExecutor.batchUpdateWithFailures(dbConfig, updateSql, queryParam); // 如果更新失败,返回错误信息 if(!batchedUpdate.isSuccess()){ return Result.fail(batchedUpdate.getError()); }else { failedList.addAll(batchedUpdate.getData()); } } // 更新操作成功,返回成功信息和更新的总行数 return Result.success(failedList); } catch (Exception e) { // 记录错误日志 logger.error("动态更新失败", e); // 返回更新失败的Result对象,包含异常信息 return Result.fail("动态更新失败: " + e.getMessage()); } } /** * 执行插入操作 * * @param dbConfig 数据库配置信息 * @param tableName 表名 * @param dbParams 数据库参数服务处理结果,包含插入所需的字段和值 * @return 返回插入操作的结果,包括成功或失败及受影响的行数 */ private Result execInsert(Map dbConfig, String tableName, DbParamsService.ProcessedResult dbParams){ try { // 检查是否存在新增字段,若存在则创建表结构 Map addColumn = dbParams.getAddColumns(); // "c" : value if (!addColumn.isEmpty()) { // 不存在的列数量是否大于0 // 创建表 或者创建字段 Result createTableResult = tableStructureManager.createTable(dbConfig, tableName, addColumn); if (!createTableResult.isSuccess()) { return createTableResult; } } // 获取插入的列名和对应的值,执行批量插入操作 String insertColumns = dbParams.getInsertColumns(); List> insertParam = dbParams.getInsertValues(); // 占位符对应的value集合 int insertCount = 0; if (!insertParam.isEmpty()) { // 新增 Result batchInsert = jdbcExecutor.batchUpdate(dbConfig, insertColumns, insertParam); if(!batchInsert.isSuccess()){ return Result.fail(batchInsert.getError()); } insertCount = insertCount + batchInsert.getData(); } // 检查是否存在更新条件,若存在则执行更新操作 Map>> queryConditionList = dbParams.getQueryConditions(); if(!queryConditionList.isEmpty()){ Result updated = execUpdate(dbConfig,dbParams); if(!updated.isSuccess()){ return Result.fail(updated.getError()); } insertCount = insertCount + updated.getData(); } // 返回插入操作的结果,包括受影响的行数 return Result.success(insertCount); } catch (Exception e) { logger.error("新增错误", e); return Result.fail("新增错误", e); } } /** * 执行数据库更新操作 * * @param dbConfig 数据库配置信息,包含连接数据库所需的参数 * @param dbParams 处理后的数据库参数对象,包含更新所需的列和查询条件 * @return 返回一个Result对象,包含受影响的行数如果更新操作失败,返回失败的Result对象 */ private Result execUpdate(Map dbConfig, DbParamsService.ProcessedResult dbParams){ try { // 获取需要更新的列字符串 String updateColumns = dbParams.getUpdateColumns(); // 初始化更新计数器 int updateCount = 0; // 遍历查询条件,执行更新操作 for(String queryCondition : dbParams.getQueryConditions().keySet()){ // 获取当前查询条件的参数 List> queryParam = dbParams.getQueryConditions().get(queryCondition); // 拼接更新SQL语句 , sql拼接完成 String updateSql = updateColumns.concat(" where ").concat(queryCondition); // 执行批量更新操作 Result batchedUpdate = jdbcExecutor.batchUpdate(dbConfig, updateSql, queryParam); // 如果更新失败,返回错误信息 if(!batchedUpdate.isSuccess()){ return Result.fail(batchedUpdate.getError()); } // 累加更新的行数 updateCount = updateCount + batchedUpdate.getData(); } // 更新操作成功,返回成功信息和更新的总行数 return Result.success(updateCount); } catch (Exception e) { // 记录错误日志 logger.error("动态更新失败", e); // 返回更新失败的Result对象,包含异常信息 return Result.fail("动态更新失败: " + e.getMessage()); } } /** * 统一删除入口,自动判断数据格式类型并执行删除操作 * * @param dbConfig 数据库连接信息 * @param dbParams 删除参数 * @return 删除结果 */ public Result execDelete(DbParamsService.ProcessedResult dbParams, Map dbConfig) { try { // 获取删除列字符串 String deleteColumns = dbParams.getDeleteColumns(); StringBuilder whereString = new StringBuilder(); List whereParam = new CopyOnWriteArrayList<>(); whereString.append(deleteColumns).append(" where "); consolidateConditional(dbParams, whereString, whereParam); return jdbcExecutor.update(dbConfig, whereString.toString(), whereParam); } catch (Exception e) { // 记录错误日志 logger.error("动态删除失败", e); // 返回删除失败的结果 return Result.fail("动态删除失败: " + e.getMessage()); } } /** * 单条插入/更新(带条件判断) * 此方法用于在数据库中插入或更新一条记录 * 它通过判断参数中的"event"字段来决定是插入还是更新操作 * 注意:此方法不会直接执行插入或更新操作,而是将操作类型和数据传递给dbUpdate方法进行处理 * * @param dbConfig 数据库配置信息,包括数据库URL、用户名、密码等 * @param tableName 要操作的表名 * @param params 插入或更新的数据,以及操作类型(通过"event"字段指定) * @return 返回一个Result对象,包含受影响的行数 */ public Result>> insertWithFailures(Map dbConfig, String tableName,Map params) { // 设置操作类型为插入 params.put("event", "INSERT"); // 调用dbUpdate方法执行插入操作 return dbUpdateWithFailures( dbConfig, tableName, params); } /** * 统一更新入口,自动判断数据格式类型并执行更新操作 * * @param dbConfig 数据库连接信息 * @param tableName 表名 * @param params 更新参数 * @return 更新结果 */ public Result>> updateWithFailures(Map dbConfig, String tableName,Map params) { // 在参数中添加事件标识,表明这是一个更新操作 params.put("event", "UPDATE"); // 调用数据库更新方法,执行实际的更新操作 return dbUpdateWithFailures(dbConfig, tableName, params); } /** * 单条插入/更新(带条件判断) * 此方法用于在数据库中插入或更新一条记录 * 它通过判断参数中的"event"字段来决定是插入还是更新操作 * 注意:此方法不会直接执行插入或更新操作,而是将操作类型和数据传递给dbUpdate方法进行处理 * * @param dbConfig 数据库配置信息,包括数据库URL、用户名、密码等 * @param tableName 要操作的表名 * @param params 插入或更新的数据,以及操作类型(通过"event"字段指定) * @return 返回一个Result对象,包含受影响的行数 */ public Result insert(Map dbConfig, String tableName,Map params) { // 设置操作类型为插入 params.put("event", "INSERT"); // 调用dbUpdate方法执行插入操作 return dbUpdate( dbConfig, tableName, params); } /** * 统一更新入口,自动判断数据格式类型并执行更新操作 * * @param dbConfig 数据库连接信息 * @param tableName 表名 * @param params 更新参数 * @return 更新结果 */ public Result update(Map dbConfig, String tableName,Map params) { // 在参数中添加事件标识,表明这是一个更新操作 params.put("event", "UPDATE"); // 调用数据库更新方法,执行实际的更新操作 return dbUpdate(dbConfig, tableName, params); } /** * 删除指定表中的记录 * 此方法通过更新数据库记录的方式实现逻辑删除它首先在参数中添加一个表示删除事件的字段, * 然后调用dbUpdate方法来执行数据库更新操作这种方法的设计允许系统灵活地处理删除操作, * 例如,可以在dbUpdate方法中添加审计日志、触发其他业务逻辑等 * * @param dbConfig 数据库配置信息,包含连接数据库所需的信息 * @param tableName 要进行删除操作的表名 * @param params 删除操作的参数,包括但不限于标识删除事件的字段和其他可能的条件字段 * @return 返回一个Result对象,包含受影响的行数如果删除失败,Result对象中应包含错误信息 */ public Result delete(Map dbConfig, String tableName,Map params) { // 在参数中添加表示删除事件的字段,以便在后续的数据库更新中标识这是一个删除操作 params.put("event", "DELETE"); // 调用数据库更新方法来执行实际的删除操作 return dbUpdate( dbConfig, tableName, params); } //---------------------------------------------------------------------------------------- public Result>> search(Map dbConfig, String tableName, Map params) { try { //参数预处理为标准参数 Result processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName); if (!processDataContextResult.isSuccess()) { return Result.fail(processDataContextResult.getError()); } DbParamsService.ProcessedResult dbParams = processDataContextResult.getData(); String event = dbParams.getEvent(); if(!event.equalsIgnoreCase("SELECT")){ return Result.fail("event 不存在或为空"); } //获取分页信息 int page = dbParams.getPage(); int pageSize = dbParams.getPageSize(); String selectColumns = dbParams.getSelectColumns();//查询语句 StringBuilder whereString = new StringBuilder(); List whereParam = new CopyOnWriteArrayList<>(); whereString.append(selectColumns).append(" WHERE "); consolidateConditional(dbParams, whereString, whereParam); return jdbcExecutor.jdbcSearch(dbConfig, whereString.toString(), whereParam, page, pageSize); } catch (Exception e) { logger.error("动态查询失败", e); return Result.fail("动态查询失败: " + e.getMessage()); } } /** * sql查询,用问号作为占位符,必须严格按照顺序执行查询 * @param dbConfig * @param params * @return */ public Result>> searchBySql(Map dbConfig, Map params){ //从 params 参数 获取 List whereParam = new CopyOnWriteArrayList<>(); String event = params.getOrDefault("event","").toString(); if(!StringUtils.hasText(event)||!event.equalsIgnoreCase("SELECT")){ return Result.fail("event 不存在或为空"); } String sql = params.getOrDefault("sql","").toString(); Object dataContent = params.get("dataContent"); logger.info("查询入参:{}", JSONObject.wrap(params).toString()); if (Objects.nonNull(dataContent)){ if (dataContent instanceof Map){ // 只查询单个 logger.info("单个查询"); Map obj = (Map)dataContent; List object = (List) obj.get("conditions"); if (!CollectionUtils.isEmpty(object)){ whereParam = object; return jdbcExecutor.queryForSql(dbConfig,sql, whereParam); }else { return Result.fail("参数解析异常"); } }else if (dataContent instanceof List dataContentList) { // 如果是多个conditions 那么会循环查询,将结果合并,不去重 // 集合查询 Set> set = new CopyOnWriteArraySet<>(); for (Object o : dataContentList) { Map queryParam = (Map) o; if (Objects.isNull(queryParam)) continue; List aDefault = (List) queryParam.getOrDefault("conditions", null); if (CollectionUtils.isEmpty(aDefault)) continue; Result>> result = jdbcExecutor.queryForSql(dbConfig, sql, aDefault); if (result.isSuccess()&&!CollectionUtils.isEmpty(result.getData())&&result.getData().size()>0){ set.addAll(result.getData()); } } return Result.success(new ArrayList<>(set)); } } return Result.fail("参数格式不正确"); } /** * 统一查询入口,自动判断数据格式类型并执行查询操作 * * @param dbConfig 数据库连接信息 * @param tableName 表名 * @param params 查询参数 * @return 查询结果列表 */ public Result> query(Map dbConfig, String tableName, Map params, Function rowMapper) { try { //参数预处理为标准参数 Result processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName); if (!processDataContextResult.isSuccess()) { return Result.fail(processDataContextResult.getError()); } DbParamsService.ProcessedResult dbParams = processDataContextResult.getData(); String event = dbParams.getEvent(); if(!event.equalsIgnoreCase("SELECT")){ return Result.fail("event 不存在或为空"); } //获取分页信息 int page = dbParams.getPage(); int pageSize = dbParams.getPageSize(); String selectColumns = dbParams.getSelectColumns();//查询语句 StringBuilder whereString = new StringBuilder(); List whereParam = new CopyOnWriteArrayList<>(); whereString.append(selectColumns).append(" WHERE "); consolidateConditional(dbParams, whereString, whereParam); return jdbcExecutor.query(dbConfig, whereString.toString(), whereParam, page, pageSize, rowMapper); } catch (Exception e) { logger.error("动态查询失败", e); return Result.fail("动态查询失败: " + e.getMessage()); } } public Result>> query(Map dbConfig, String tableName, Map params) { try { //参数预处理为标准参数 Result processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName); if (!processDataContextResult.isSuccess()) { return Result.fail(processDataContextResult.getError()); } DbParamsService.ProcessedResult dbParams = processDataContextResult.getData(); String event = dbParams.getEvent(); if (!event.equalsIgnoreCase("SELECT")) { return Result.fail("event 不存在或为空"); } //获取分页信息 int page = dbParams.getPage(); int pageSize = dbParams.getPageSize(); String selectColumns = dbParams.getSelectColumns();//查询语句 StringBuilder whereString = new StringBuilder(); List whereParam = new CopyOnWriteArrayList<>(); whereString.append(selectColumns).append(" where "); consolidateConditional(dbParams, whereString, whereParam); return jdbcExecutor.queryForList(dbConfig, whereString.toString(), whereParam, page, pageSize); } catch (Exception e) { logger.error("动态查询失败", e); return Result.fail("动态查询失败: " + e.getMessage()); } } /** * 带缓存的查询方法 * @param dbConfig 数据库配置 * @param tableName 表名 * @param params 查询参数 * @param useCache true: 优先使用缓存; false: 强制刷新缓存 * @return 查询结果 */ public Result> find(Map dbConfig, String tableName, Map params, Function rowMapper, boolean useCache) { try { Result> validatedConnection = dbUtils.validateConnection(dbConfig); if(!validatedConnection.isSuccess()){ return Result.fail(validatedConnection.getError()) ; } String dbKey = validatedConnection.getData().get("dbKey"); String cacheKey = dbKey + tableName + deepCopyParams(params); // 缓存处理逻辑 if (useCache) { // 优先使用缓存 Result> cachedResult = getFromCache(cacheKey); if (cachedResult != null && cachedResult.isSuccess()) { return cachedResult; // 直接返回Result对象 } } else { // 强制刷新时清除旧缓存 queryCache.invalidate(cacheKey); } // 执行真实查询 Map newParams = new HashMap<>(params); newParams.put("event", "SELECT"); Result> result = query(dbConfig, tableName, newParams,rowMapper); // 更新缓存 if (result.isSuccess()) { queryCache.put(cacheKey, result.getData()); } return result; } catch (Exception e) { logger.error("缓存查询失败", e); return Result.fail("缓存查询失败: " + e.getMessage()); } } /** * 深度拷贝参数以防止外部修改影响缓存 * 该方法主要用于创建给定参数映射的深度副本,以确保原始映射及其包含的列表或映射不会被外部修改 * 这对于维护缓存的一致性和完整性至关重要 * * @param params 需要深度拷贝的原始参数映射 * @return 返回一个包含所有原始参数的深度副本映射 */ private Map deepCopyParams(Map params) { Map copy = new HashMap<>(); // 遍历原始参数映射 for (Map.Entry entry : params.entrySet()) { // 当值为Map类型时,创建一个新的HashMap并复制内容 if (entry.getValue() instanceof Map) { copy.put(entry.getKey(), new HashMap<>((Map) entry.getValue())); // 当值为List类型时,创建一个新的ArrayList并复制内容 } else if (entry.getValue() instanceof List) { copy.put(entry.getKey(), new ArrayList<>((List) entry.getValue())); // 对于其他类型,直接复制值 } else { copy.put(entry.getKey(), entry.getValue()); } } // 返回深度拷贝后的参数映射 return copy; } /** * 从缓存中获取指定键对应的值 * 此方法用于从缓存中检索与给定键关联的列表数据如果缓存中没有找到对应的键,则返回null * * @param key 缓存中的键,用于检索数据 * @param 泛型参数,表示列表中元素的类型 * @return 如果找到数据,则返回包含数据的Result对象;否则返回null */ private Result> getFromCache(String key) { // 从缓存中尝试获取数据 List result = queryCache.getIfPresent(key); // 如果没有找到数据,则返回null if (result == null) return null; // 将找到的数据转换为指定的泛型类型,并封装在Result对象中返回 @SuppressWarnings("unchecked") List typedResult = (List) result; return Result.success(typedResult); } //-------------------------------------------------------------------------- // 合并条件语句到SQL查询的where子句中 /** * 将处理后的数据库参数整合到SQL查询的where子句中 * 此方法主要负责处理查询条件的合并,将多个查询条件用"or"连接,并处理权限条件,用"and"连接 * 如果最终生成的where子句以"where"关键字开始,则将其删除,以避免SQL语法错误 * * @param dbParams 处理后的数据库参数对象,包含查询条件和权限信息 * @param whereString 用于存储最终where子句的StringBuilder对象 * @param whereParam 用于存储查询条件参数的列表 */ private void consolidateConditional(DbParamsService.ProcessedResult dbParams, StringBuilder whereString, List whereParam){ // 临时存储where子句的字符串 String tempWhereString = ""; // 获取查询条件及查询参数 Map>> queryConditionsList = dbParams.getQueryConditions(); // 如果存在查询条件,则处理这些条件 if(!queryConditionsList.isEmpty()){ // 存储所有的查询条件 List queryConditions = new ArrayList<>(); // 遍历每个查询条件,将其用括号包裹后添加到查询条件列表中,并合并参数到whereParam中 for(String key : queryConditionsList.keySet()){ queryConditions.add("(".concat(key).concat(")")); List> lists = queryConditionsList.get(key);//针对同一个where条件的X行参数 //单行的参数 for (List rowQueryParam : lists) { whereParam.addAll(rowQueryParam); } } // 使用" or "连接所有的查询条件 tempWhereString = String.join(" or ", queryConditions); // 将临时where子句添加到最终的where子句中 whereString.append(tempWhereString); } // 获取权限条件 String permission = dbParams.getPermission(); // 如果权限条件不为空,则将其添加到where子句中 if(permission != null && !permission.isEmpty()){ // 如果临时where子句不为空,则添加"and"连接权限条件和查询条件 if(!tempWhereString.isEmpty()){ whereString.append(" and "); } // 将权限条件用括号包裹后添加到where子句中 whereString.append(" (").append(permission).append(")"); } // 如果最终的where子句以"where"关键字开始,则将其删除,以避免SQL语法错误 if(whereString.toString().endsWith(" where ")){ whereString.delete(whereString.length() - 6, whereString.length()); } } }