DbExecutor.java 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. package com.bfkj.unidia.DataBaseUtils;
  2. import com.bfkj.unidia.Result;
  3. import com.github.benmanes.caffeine.cache.Cache;
  4. import com.github.benmanes.caffeine.cache.Caffeine;
  5. import org.json.JSONArray;
  6. import org.json.JSONObject;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. import org.springframework.util.CollectionUtils;
  12. import org.springframework.util.StringUtils;
  13. import java.sql.ResultSet;
  14. import java.util.*;
  15. import java.util.concurrent.CopyOnWriteArrayList;
  16. import java.util.concurrent.CopyOnWriteArraySet;
  17. import java.util.concurrent.TimeUnit;
  18. import java.util.function.Function;
  19. import static com.bfkj.unidia.cacheUtils.CacheUtil.buildCaffeineCache;
  20. @Service
  21. public class DbExecutor {
  22. private static final Logger logger = LoggerFactory.getLogger(DbExecutor.class);
  23. private final JdbcExecutor jdbcExecutor;
  24. private final TableStructureManager tableStructureManager;
  25. private final DbUtils dbUtils;
  26. private final DbParamsService dbParamsService;
  27. @Autowired
  28. public DbExecutor(JdbcExecutor jdbcExecutor,
  29. TableStructureManager tableStructureManager,
  30. DbUtils dbUtils,
  31. DbParamsService dbParamsService) {
  32. this.jdbcExecutor = jdbcExecutor;
  33. this.tableStructureManager = tableStructureManager;
  34. this.dbUtils = dbUtils;
  35. this.dbParamsService = dbParamsService;
  36. }
  37. private final Cache<String, List<?>> queryCache = buildCaffeineCache();
  38. /**
  39. * 更新数据库记录
  40. * 该方法根据提供的参数和数据库配置,执行相应的数据库操作(插入、更新、删除)
  41. *
  42. * @param dbConfig 数据库配置信息,包括连接字符串、用户名、密码等
  43. * @param tableName 需要操作的数据库表名
  44. * @param params 操作所需的参数,包括操作类型(INSERT、UPDATE、DELETE)及相应的数据
  45. * @return 返回一个Result对象,包含操作结果,主要是影响的行数
  46. */
  47. public Result<Integer> dbUpdate(Map<String, String> dbConfig, String tableName, Map<String, Object> params) {
  48. //参数预处理,包括参数校验 (会拼接成完整的sql)
  49. Result<DbParamsService.ProcessedResult> processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName);
  50. //如果参数不合法,返回错误信息
  51. if (!processDataContextResult.isSuccess()) {
  52. return Result.fail(processDataContextResult.getError());
  53. }
  54. DbParamsService.ProcessedResult dbParams = processDataContextResult.getData();
  55. //依据不同事件进行操作
  56. String event = dbParams.getEvent().toUpperCase();
  57. //根据事件类型执行相应的数据库操作
  58. if(event.equals("INSERT")){//新增
  59. return execInsert(dbConfig, tableName, dbParams);
  60. }
  61. if(event.equals("UPDATE")){//更新
  62. return execUpdate(dbConfig,dbParams);
  63. }
  64. if(event.equals("DELETE")){//删除
  65. return execDelete(dbParams, dbConfig);
  66. }
  67. //如果事件类型不支持,返回错误信息
  68. return Result.fail("不支持的事件类型");
  69. }
  70. /**
  71. * 更新数据库记录
  72. * 该方法根据提供的参数和数据库配置,执行相应的数据库操作(插入、更新、删除)
  73. *
  74. * @param dbConfig 数据库配置信息,包括连接字符串、用户名、密码等
  75. * @param tableName 需要操作的数据库表名
  76. * @param params 操作所需的参数,包括操作类型(INSERT、UPDATE、DELETE)及相应的数据
  77. * @return 返回一个Result对象,包含操作结果,主要是影响的行数
  78. */
  79. public Result<List<List<Object>>> dbUpdateWithFailures(Map<String, String> dbConfig, String tableName, Map<String, Object> params) {
  80. //参数预处理,包括参数校验 (会拼接成完整的sql)
  81. Result<DbParamsService.ProcessedResult> processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName);
  82. //如果参数不合法,返回错误信息
  83. if (!processDataContextResult.isSuccess()) {
  84. return Result.fail(processDataContextResult.getError());
  85. }
  86. DbParamsService.ProcessedResult dbParams = processDataContextResult.getData();
  87. //依据不同事件进行操作
  88. String event = dbParams.getEvent().toUpperCase();
  89. //根据事件类型执行相应的数据库操作
  90. if(event.equals("INSERT")){//新增
  91. return execInsertWithFailures(dbConfig, tableName, dbParams);
  92. }
  93. if(event.equals("UPDATE")){//更新
  94. return execUpdateWithFailures(dbConfig,dbParams);
  95. }
  96. //如果事件类型不支持,返回错误信息
  97. return Result.fail("不支持的事件类型");
  98. }
  99. /**
  100. * 执行插入操作
  101. *
  102. * @param dbConfig 数据库配置信息
  103. * @param tableName 表名
  104. * @param dbParams 数据库参数服务处理结果,包含插入所需的字段和值
  105. * @return 返回插入操作的结果,包括成功或失败及受影响的行数
  106. */
  107. private Result<List<List<Object>>> execInsertWithFailures(Map<String, String> dbConfig, String tableName,
  108. DbParamsService.ProcessedResult dbParams){
  109. try {
  110. // 检查是否存在新增字段,若存在则创建表结构
  111. Map<String, Object> addColumn = dbParams.getAddColumns(); // "c" : value
  112. if (!addColumn.isEmpty()) { // 不存在的列数量是否大于0
  113. // 创建表 或者创建字段
  114. Result<Integer> createTableResult = tableStructureManager.createTable(dbConfig, tableName, addColumn);
  115. if (!createTableResult.isSuccess()) {
  116. return Result.fail("表创建失败");
  117. }
  118. }
  119. // 获取插入的列名和对应的值,执行批量插入操作
  120. String insertColumns = dbParams.getInsertColumns();
  121. List<List<Object>> insertParam = dbParams.getInsertValues(); // 占位符对应的value集合
  122. if (!insertParam.isEmpty()) { // 新增
  123. Result<List<List<Object>>> batchInsert = jdbcExecutor.batchUpdateWithFailures(dbConfig, insertColumns, insertParam);
  124. if(!batchInsert.isSuccess()){
  125. return Result.fail(batchInsert.getError());
  126. }
  127. return Result.success(batchInsert.getData());
  128. }
  129. // 检查是否存在更新条件,若存在则执行更新操作
  130. Map<String,List<List<Object>>> queryConditionList = dbParams.getQueryConditions();
  131. if(!queryConditionList.isEmpty()){
  132. Result<List<List<Object>>> updated = execUpdateWithFailures(dbConfig,dbParams);
  133. if(!updated.isSuccess()){
  134. return Result.fail(updated.getError());
  135. }
  136. return Result.success(updated.getData());
  137. }
  138. // 返回插入操作的结果,包括受影响的行数
  139. return Result.success(null);
  140. } catch (Exception e) {
  141. logger.error("新增错误", e);
  142. return Result.fail("新增错误", e);
  143. }
  144. }
  145. /**
  146. * 执行数据库更新操作
  147. *
  148. * @param dbConfig 数据库配置信息,包含连接数据库所需的参数
  149. * @param dbParams 处理后的数据库参数对象,包含更新所需的列和查询条件
  150. * @return 返回一个Result对象,包含受影响的行数如果更新操作失败,返回失败的Result对象
  151. */
  152. private Result<List<List<Object>>> execUpdateWithFailures(Map<String, String> dbConfig,
  153. DbParamsService.ProcessedResult dbParams){
  154. try {
  155. // 获取需要更新的列字符串
  156. String updateColumns = dbParams.getUpdateColumns();
  157. List<List<Object>> failedList = null;
  158. // 初始化更新计数器
  159. // 遍历查询条件,执行更新操作
  160. for(String queryCondition : dbParams.getQueryConditions().keySet()){
  161. // 获取当前查询条件的参数
  162. List<List<Object>> queryParam = dbParams.getQueryConditions().get(queryCondition);
  163. // 拼接更新SQL语句 , sql拼接完成
  164. String updateSql = updateColumns.concat(" where ").concat(queryCondition);
  165. // 执行批量更新操作
  166. Result<List<List<Object>>> batchedUpdate = jdbcExecutor.batchUpdateWithFailures(dbConfig, updateSql, queryParam);
  167. // 如果更新失败,返回错误信息
  168. if(!batchedUpdate.isSuccess()){
  169. return Result.fail(batchedUpdate.getError());
  170. }else {
  171. failedList.addAll(batchedUpdate.getData());
  172. }
  173. }
  174. // 更新操作成功,返回成功信息和更新的总行数
  175. return Result.success(failedList);
  176. } catch (Exception e) {
  177. // 记录错误日志
  178. logger.error("动态更新失败", e);
  179. // 返回更新失败的Result对象,包含异常信息
  180. return Result.fail("动态更新失败: " + e.getMessage());
  181. }
  182. }
  183. /**
  184. * 执行插入操作
  185. *
  186. * @param dbConfig 数据库配置信息
  187. * @param tableName 表名
  188. * @param dbParams 数据库参数服务处理结果,包含插入所需的字段和值
  189. * @return 返回插入操作的结果,包括成功或失败及受影响的行数
  190. */
  191. private Result<Integer> execInsert(Map<String, String> dbConfig, String tableName,
  192. DbParamsService.ProcessedResult dbParams){
  193. try {
  194. // 检查是否存在新增字段,若存在则创建表结构
  195. Map<String, Object> addColumn = dbParams.getAddColumns(); // "c" : value
  196. if (!addColumn.isEmpty()) { // 不存在的列数量是否大于0
  197. // 创建表 或者创建字段
  198. Result<Integer> createTableResult = tableStructureManager.createTable(dbConfig, tableName, addColumn);
  199. if (!createTableResult.isSuccess()) {
  200. return createTableResult;
  201. }
  202. }
  203. // 获取插入的列名和对应的值,执行批量插入操作
  204. String insertColumns = dbParams.getInsertColumns();
  205. List<List<Object>> insertParam = dbParams.getInsertValues(); // 占位符对应的value集合
  206. int insertCount = 0;
  207. if (!insertParam.isEmpty()) { // 新增
  208. Result<Integer> batchInsert = jdbcExecutor.batchUpdate(dbConfig, insertColumns, insertParam);
  209. if(!batchInsert.isSuccess()){
  210. return Result.fail(batchInsert.getError());
  211. }
  212. insertCount = insertCount + batchInsert.getData();
  213. }
  214. // 检查是否存在更新条件,若存在则执行更新操作
  215. Map<String,List<List<Object>>> queryConditionList = dbParams.getQueryConditions();
  216. if(!queryConditionList.isEmpty()){
  217. Result<Integer> updated = execUpdate(dbConfig,dbParams);
  218. if(!updated.isSuccess()){
  219. return Result.fail(updated.getError());
  220. }
  221. insertCount = insertCount + updated.getData();
  222. }
  223. // 返回插入操作的结果,包括受影响的行数
  224. return Result.success(insertCount);
  225. } catch (Exception e) {
  226. logger.error("新增错误", e);
  227. return Result.fail("新增错误", e);
  228. }
  229. }
  230. /**
  231. * 执行数据库更新操作
  232. *
  233. * @param dbConfig 数据库配置信息,包含连接数据库所需的参数
  234. * @param dbParams 处理后的数据库参数对象,包含更新所需的列和查询条件
  235. * @return 返回一个Result对象,包含受影响的行数如果更新操作失败,返回失败的Result对象
  236. */
  237. private Result<Integer> execUpdate(Map<String, String> dbConfig,
  238. DbParamsService.ProcessedResult dbParams){
  239. try {
  240. // 获取需要更新的列字符串
  241. String updateColumns = dbParams.getUpdateColumns();
  242. // 初始化更新计数器
  243. int updateCount = 0;
  244. // 遍历查询条件,执行更新操作
  245. for(String queryCondition : dbParams.getQueryConditions().keySet()){
  246. // 获取当前查询条件的参数
  247. List<List<Object>> queryParam = dbParams.getQueryConditions().get(queryCondition);
  248. // 拼接更新SQL语句 , sql拼接完成
  249. String updateSql = updateColumns.concat(" where ").concat(queryCondition);
  250. // 执行批量更新操作
  251. Result<Integer> batchedUpdate = jdbcExecutor.batchUpdate(dbConfig, updateSql, queryParam);
  252. // 如果更新失败,返回错误信息
  253. if(!batchedUpdate.isSuccess()){
  254. return Result.fail(batchedUpdate.getError());
  255. }
  256. // 累加更新的行数
  257. updateCount = updateCount + batchedUpdate.getData();
  258. }
  259. // 更新操作成功,返回成功信息和更新的总行数
  260. return Result.success(updateCount);
  261. } catch (Exception e) {
  262. // 记录错误日志
  263. logger.error("动态更新失败", e);
  264. // 返回更新失败的Result对象,包含异常信息
  265. return Result.fail("动态更新失败: " + e.getMessage());
  266. }
  267. }
  268. /**
  269. * 统一删除入口,自动判断数据格式类型并执行删除操作
  270. *
  271. * @param dbConfig 数据库连接信息
  272. * @param dbParams 删除参数
  273. * @return 删除结果
  274. */
  275. public Result<Integer> execDelete(DbParamsService.ProcessedResult dbParams, Map<String, String> dbConfig) {
  276. try {
  277. // 获取删除列字符串
  278. String deleteColumns = dbParams.getDeleteColumns();
  279. StringBuilder whereString = new StringBuilder();
  280. List<Object> whereParam = new CopyOnWriteArrayList<>();
  281. whereString.append(deleteColumns).append(" where ");
  282. consolidateConditional(dbParams, whereString, whereParam);
  283. return jdbcExecutor.update(dbConfig, whereString.toString(), whereParam);
  284. } catch (Exception e) {
  285. // 记录错误日志
  286. logger.error("动态删除失败", e);
  287. // 返回删除失败的结果
  288. return Result.fail("动态删除失败: " + e.getMessage());
  289. }
  290. }
  291. /**
  292. * 单条插入/更新(带条件判断)
  293. * 此方法用于在数据库中插入或更新一条记录
  294. * 它通过判断参数中的"event"字段来决定是插入还是更新操作
  295. * 注意:此方法不会直接执行插入或更新操作,而是将操作类型和数据传递给dbUpdate方法进行处理
  296. *
  297. * @param dbConfig 数据库配置信息,包括数据库URL、用户名、密码等
  298. * @param tableName 要操作的表名
  299. * @param params 插入或更新的数据,以及操作类型(通过"event"字段指定)
  300. * @return 返回一个Result对象,包含受影响的行数
  301. */
  302. public Result<List<List<Object>>> insertWithFailures(Map<String, String> dbConfig, String tableName,Map<String, Object> params) {
  303. // 设置操作类型为插入
  304. params.put("event", "INSERT");
  305. // 调用dbUpdate方法执行插入操作
  306. return dbUpdateWithFailures( dbConfig, tableName, params);
  307. }
  308. /**
  309. * 统一更新入口,自动判断数据格式类型并执行更新操作
  310. *
  311. * @param dbConfig 数据库连接信息
  312. * @param tableName 表名
  313. * @param params 更新参数
  314. * @return 更新结果
  315. */
  316. public Result<List<List<Object>>> updateWithFailures(Map<String, String> dbConfig, String tableName,Map<String, Object> params) {
  317. // 在参数中添加事件标识,表明这是一个更新操作
  318. params.put("event", "UPDATE");
  319. // 调用数据库更新方法,执行实际的更新操作
  320. return dbUpdateWithFailures(dbConfig, tableName, params);
  321. }
  322. /**
  323. * 单条插入/更新(带条件判断)
  324. * 此方法用于在数据库中插入或更新一条记录
  325. * 它通过判断参数中的"event"字段来决定是插入还是更新操作
  326. * 注意:此方法不会直接执行插入或更新操作,而是将操作类型和数据传递给dbUpdate方法进行处理
  327. *
  328. * @param dbConfig 数据库配置信息,包括数据库URL、用户名、密码等
  329. * @param tableName 要操作的表名
  330. * @param params 插入或更新的数据,以及操作类型(通过"event"字段指定)
  331. * @return 返回一个Result对象,包含受影响的行数
  332. */
  333. public Result<Integer> insert(Map<String, String> dbConfig, String tableName,Map<String, Object> params) {
  334. // 设置操作类型为插入
  335. params.put("event", "INSERT");
  336. // 调用dbUpdate方法执行插入操作
  337. return dbUpdate( dbConfig, tableName, params);
  338. }
  339. /**
  340. * 统一更新入口,自动判断数据格式类型并执行更新操作
  341. *
  342. * @param dbConfig 数据库连接信息
  343. * @param tableName 表名
  344. * @param params 更新参数
  345. * @return 更新结果
  346. */
  347. public Result<Integer> update(Map<String, String> dbConfig, String tableName,Map<String, Object> params) {
  348. // 在参数中添加事件标识,表明这是一个更新操作
  349. params.put("event", "UPDATE");
  350. // 调用数据库更新方法,执行实际的更新操作
  351. return dbUpdate(dbConfig, tableName, params);
  352. }
  353. /**
  354. * 删除指定表中的记录
  355. * 此方法通过更新数据库记录的方式实现逻辑删除它首先在参数中添加一个表示删除事件的字段,
  356. * 然后调用dbUpdate方法来执行数据库更新操作这种方法的设计允许系统灵活地处理删除操作,
  357. * 例如,可以在dbUpdate方法中添加审计日志、触发其他业务逻辑等
  358. *
  359. * @param dbConfig 数据库配置信息,包含连接数据库所需的信息
  360. * @param tableName 要进行删除操作的表名
  361. * @param params 删除操作的参数,包括但不限于标识删除事件的字段和其他可能的条件字段
  362. * @return 返回一个Result对象,包含受影响的行数如果删除失败,Result对象中应包含错误信息
  363. */
  364. public Result<Integer> delete(Map<String, String> dbConfig, String tableName,Map<String, Object> params) {
  365. // 在参数中添加表示删除事件的字段,以便在后续的数据库更新中标识这是一个删除操作
  366. params.put("event", "DELETE");
  367. // 调用数据库更新方法来执行实际的删除操作
  368. return dbUpdate( dbConfig, tableName, params);
  369. }
  370. //----------------------------------------------------------------------------------------
  371. public Result<List<Map<String, Object>>> search(Map<String, String> dbConfig, String tableName, Map<String, Object> params) {
  372. try {
  373. //参数预处理为标准参数
  374. Result<DbParamsService.ProcessedResult> processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName);
  375. if (!processDataContextResult.isSuccess()) {
  376. return Result.fail(processDataContextResult.getError());
  377. }
  378. DbParamsService.ProcessedResult dbParams = processDataContextResult.getData();
  379. String event = dbParams.getEvent();
  380. if(!event.equalsIgnoreCase("SELECT")){
  381. return Result.fail("event 不存在或为空");
  382. }
  383. //获取分页信息
  384. int page = dbParams.getPage();
  385. int pageSize = dbParams.getPageSize();
  386. String selectColumns = dbParams.getSelectColumns();//查询语句
  387. StringBuilder whereString = new StringBuilder();
  388. List<Object> whereParam = new CopyOnWriteArrayList<>();
  389. whereString.append(selectColumns).append(" WHERE ");
  390. consolidateConditional(dbParams, whereString, whereParam);
  391. return jdbcExecutor.jdbcSearch(dbConfig, whereString.toString(), whereParam, page, pageSize);
  392. } catch (Exception e) {
  393. logger.error("动态查询失败", e);
  394. return Result.fail("动态查询失败: " + e.getMessage());
  395. }
  396. }
  397. /**
  398. * sql查询,用问号作为占位符,必须严格按照顺序执行查询
  399. * @param dbConfig
  400. * @param params
  401. * @return
  402. */
  403. public Result<List<Map<String, Object>>> searchBySql(Map<String, String> dbConfig, Map<String, Object> params){
  404. //从 params 参数 获取
  405. List<Object> whereParam = new CopyOnWriteArrayList<>();
  406. String event = params.getOrDefault("event","").toString();
  407. if(!StringUtils.hasText(event)||!event.equalsIgnoreCase("SELECT")){
  408. return Result.fail("event 不存在或为空");
  409. }
  410. String sql = params.getOrDefault("sql","").toString();
  411. Object dataContent = params.get("dataContent");
  412. logger.info("查询入参:{}", JSONObject.wrap(params).toString());
  413. if (Objects.nonNull(dataContent)){
  414. if (dataContent instanceof Map<?,?>){ // 只查询单个
  415. logger.info("单个查询");
  416. Map<String, Object> obj = (Map<String, Object>)dataContent;
  417. List<Object> object = (List<Object>) obj.get("conditions");
  418. if (!CollectionUtils.isEmpty(object)){
  419. whereParam = object;
  420. return jdbcExecutor.queryForSql(dbConfig,sql, whereParam);
  421. }else {
  422. return Result.fail("参数解析异常");
  423. }
  424. }else if (dataContent instanceof List<?> dataContentList) { // 如果是多个conditions 那么会循环查询,将结果合并,不去重
  425. // 集合查询
  426. Set<Map<String, Object>> set = new CopyOnWriteArraySet<>();
  427. for (Object o : dataContentList) {
  428. Map<String,Object> queryParam = (Map<String,Object>) o;
  429. if (Objects.isNull(queryParam)) continue;
  430. List<Object> aDefault = (List<Object>) queryParam.getOrDefault("conditions", null);
  431. if (CollectionUtils.isEmpty(aDefault)) continue;
  432. Result<List<Map<String, Object>>> result = jdbcExecutor.queryForSql(dbConfig, sql, aDefault);
  433. if (result.isSuccess()&&!CollectionUtils.isEmpty(result.getData())&&result.getData().size()>0){
  434. set.addAll(result.getData());
  435. }
  436. }
  437. return Result.success(new ArrayList<>(set));
  438. }
  439. }
  440. return Result.fail("参数格式不正确");
  441. }
  442. /**
  443. * 统一查询入口,自动判断数据格式类型并执行查询操作
  444. *
  445. * @param dbConfig 数据库连接信息
  446. * @param tableName 表名
  447. * @param params 查询参数
  448. * @return 查询结果列表
  449. */
  450. public <T> Result<List<T>> query(Map<String, String> dbConfig, String tableName, Map<String, Object> params, Function<ResultSet, T> rowMapper) {
  451. try {
  452. //参数预处理为标准参数
  453. Result<DbParamsService.ProcessedResult> processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName);
  454. if (!processDataContextResult.isSuccess()) {
  455. return Result.fail(processDataContextResult.getError());
  456. }
  457. DbParamsService.ProcessedResult dbParams = processDataContextResult.getData();
  458. String event = dbParams.getEvent();
  459. if(!event.equalsIgnoreCase("SELECT")){
  460. return Result.fail("event 不存在或为空");
  461. }
  462. //获取分页信息
  463. int page = dbParams.getPage();
  464. int pageSize = dbParams.getPageSize();
  465. String selectColumns = dbParams.getSelectColumns();//查询语句
  466. StringBuilder whereString = new StringBuilder();
  467. List<Object> whereParam = new CopyOnWriteArrayList<>();
  468. whereString.append(selectColumns).append(" WHERE ");
  469. consolidateConditional(dbParams, whereString, whereParam);
  470. return jdbcExecutor.query(dbConfig, whereString.toString(), whereParam, page, pageSize, rowMapper);
  471. } catch (Exception e) {
  472. logger.error("动态查询失败", e);
  473. return Result.fail("动态查询失败: " + e.getMessage());
  474. }
  475. }
  476. public <T> Result<List<Map<String, Object>>> query(Map<String, String> dbConfig, String tableName, Map<String, Object> params) {
  477. try {
  478. //参数预处理为标准参数
  479. Result<DbParamsService.ProcessedResult> processDataContextResult = dbParamsService.processExecutorParams(params, dbConfig, tableName);
  480. if (!processDataContextResult.isSuccess()) {
  481. return Result.fail(processDataContextResult.getError());
  482. }
  483. DbParamsService.ProcessedResult dbParams = processDataContextResult.getData();
  484. String event = dbParams.getEvent();
  485. if (!event.equalsIgnoreCase("SELECT")) {
  486. return Result.fail("event 不存在或为空");
  487. }
  488. //获取分页信息
  489. int page = dbParams.getPage();
  490. int pageSize = dbParams.getPageSize();
  491. String selectColumns = dbParams.getSelectColumns();//查询语句
  492. StringBuilder whereString = new StringBuilder();
  493. List<Object> whereParam = new CopyOnWriteArrayList<>();
  494. whereString.append(selectColumns).append(" where ");
  495. consolidateConditional(dbParams, whereString, whereParam);
  496. return jdbcExecutor.queryForList(dbConfig, whereString.toString(), whereParam, page, pageSize);
  497. } catch (Exception e) {
  498. logger.error("动态查询失败", e);
  499. return Result.fail("动态查询失败: " + e.getMessage());
  500. }
  501. }
  502. /**
  503. * 带缓存的查询方法
  504. * @param dbConfig 数据库配置
  505. * @param tableName 表名
  506. * @param params 查询参数
  507. * @param useCache true: 优先使用缓存; false: 强制刷新缓存
  508. * @return 查询结果
  509. */
  510. public <T> Result<List<T>> find(Map<String, String> dbConfig,
  511. String tableName,
  512. Map<String, Object> params,
  513. Function<ResultSet, T> rowMapper,
  514. boolean useCache) {
  515. try {
  516. Result<Map<String, String>> validatedConnection = dbUtils.validateConnection(dbConfig);
  517. if(!validatedConnection.isSuccess()){
  518. return Result.fail(validatedConnection.getError()) ;
  519. }
  520. String dbKey = validatedConnection.getData().get("dbKey");
  521. String cacheKey = dbKey + tableName + deepCopyParams(params);
  522. // 缓存处理逻辑
  523. if (useCache) {
  524. // 优先使用缓存
  525. Result<List<T>> cachedResult = getFromCache(cacheKey);
  526. if (cachedResult != null && cachedResult.isSuccess()) {
  527. return cachedResult; // 直接返回Result对象
  528. }
  529. } else {
  530. // 强制刷新时清除旧缓存
  531. queryCache.invalidate(cacheKey);
  532. }
  533. // 执行真实查询
  534. Map<String, Object> newParams = new HashMap<>(params);
  535. newParams.put("event", "SELECT");
  536. Result<List<T>> result = query(dbConfig, tableName, newParams,rowMapper);
  537. // 更新缓存
  538. if (result.isSuccess()) {
  539. queryCache.put(cacheKey, result.getData());
  540. }
  541. return result;
  542. } catch (Exception e) {
  543. logger.error("缓存查询失败", e);
  544. return Result.fail("缓存查询失败: " + e.getMessage());
  545. }
  546. }
  547. /**
  548. * 深度拷贝参数以防止外部修改影响缓存
  549. * 该方法主要用于创建给定参数映射的深度副本,以确保原始映射及其包含的列表或映射不会被外部修改
  550. * 这对于维护缓存的一致性和完整性至关重要
  551. *
  552. * @param params 需要深度拷贝的原始参数映射
  553. * @return 返回一个包含所有原始参数的深度副本映射
  554. */
  555. private Map<String, Object> deepCopyParams(Map<String, Object> params) {
  556. Map<String, Object> copy = new HashMap<>();
  557. // 遍历原始参数映射
  558. for (Map.Entry<String, Object> entry : params.entrySet()) {
  559. // 当值为Map类型时,创建一个新的HashMap并复制内容
  560. if (entry.getValue() instanceof Map) {
  561. copy.put(entry.getKey(), new HashMap<>((Map<?, ?>) entry.getValue()));
  562. // 当值为List类型时,创建一个新的ArrayList并复制内容
  563. } else if (entry.getValue() instanceof List) {
  564. copy.put(entry.getKey(), new ArrayList<>((List<?>) entry.getValue()));
  565. // 对于其他类型,直接复制值
  566. } else {
  567. copy.put(entry.getKey(), entry.getValue());
  568. }
  569. }
  570. // 返回深度拷贝后的参数映射
  571. return copy;
  572. }
  573. /**
  574. * 从缓存中获取指定键对应的值
  575. * 此方法用于从缓存中检索与给定键关联的列表数据如果缓存中没有找到对应的键,则返回null
  576. *
  577. * @param key 缓存中的键,用于检索数据
  578. * @param <T> 泛型参数,表示列表中元素的类型
  579. * @return 如果找到数据,则返回包含数据的Result对象;否则返回null
  580. */
  581. private <T> Result<List<T>> getFromCache(String key) {
  582. // 从缓存中尝试获取数据
  583. List<?> result = queryCache.getIfPresent(key);
  584. // 如果没有找到数据,则返回null
  585. if (result == null) return null;
  586. // 将找到的数据转换为指定的泛型类型,并封装在Result对象中返回
  587. @SuppressWarnings("unchecked")
  588. List<T> typedResult = (List<T>) result;
  589. return Result.success(typedResult);
  590. }
  591. //--------------------------------------------------------------------------
  592. // 合并条件语句到SQL查询的where子句中
  593. /**
  594. * 将处理后的数据库参数整合到SQL查询的where子句中
  595. * 此方法主要负责处理查询条件的合并,将多个查询条件用"or"连接,并处理权限条件,用"and"连接
  596. * 如果最终生成的where子句以"where"关键字开始,则将其删除,以避免SQL语法错误
  597. *
  598. * @param dbParams 处理后的数据库参数对象,包含查询条件和权限信息
  599. * @param whereString 用于存储最终where子句的StringBuilder对象
  600. * @param whereParam 用于存储查询条件参数的列表
  601. */
  602. private void consolidateConditional(DbParamsService.ProcessedResult dbParams,
  603. StringBuilder whereString,
  604. List<Object> whereParam){
  605. // 临时存储where子句的字符串
  606. String tempWhereString = "";
  607. // 获取查询条件及查询参数
  608. Map<String, List<List<Object>>> queryConditionsList = dbParams.getQueryConditions();
  609. // 如果存在查询条件,则处理这些条件
  610. if(!queryConditionsList.isEmpty()){
  611. // 存储所有的查询条件
  612. List<String> queryConditions = new ArrayList<>();
  613. // 遍历每个查询条件,将其用括号包裹后添加到查询条件列表中,并合并参数到whereParam中
  614. for(String key : queryConditionsList.keySet()){
  615. queryConditions.add("(".concat(key).concat(")"));
  616. List<List<Object>> lists = queryConditionsList.get(key);//针对同一个where条件的X行参数
  617. //单行的参数
  618. for (List<Object> rowQueryParam : lists) {
  619. whereParam.addAll(rowQueryParam);
  620. }
  621. }
  622. // 使用" or "连接所有的查询条件
  623. tempWhereString = String.join(" or ", queryConditions);
  624. // 将临时where子句添加到最终的where子句中
  625. whereString.append(tempWhereString);
  626. }
  627. // 获取权限条件
  628. String permission = dbParams.getPermission();
  629. // 如果权限条件不为空,则将其添加到where子句中
  630. if(permission != null && !permission.isEmpty()){
  631. // 如果临时where子句不为空,则添加"and"连接权限条件和查询条件
  632. if(!tempWhereString.isEmpty()){
  633. whereString.append(" and ");
  634. }
  635. // 将权限条件用括号包裹后添加到where子句中
  636. whereString.append(" (").append(permission).append(")");
  637. }
  638. // 如果最终的where子句以"where"关键字开始,则将其删除,以避免SQL语法错误
  639. if(whereString.toString().endsWith(" where ")){
  640. whereString.delete(whereString.length() - 6, whereString.length());
  641. }
  642. }
  643. }