diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysDatabaseLinkController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysDatabaseLinkController.java index 94087cdf..d6bd6368 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysDatabaseLinkController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysDatabaseLinkController.java @@ -145,5 +145,14 @@ public class SysDatabaseLinkController extends BaseController { return R.ok(sysDatabaseLinkService.querySql(linkId, sql)); } + /** + * 执行分页自定义SQL查询,返回数据List + */ + @SaCheckPermission("system:databaseLink:query") + @PostMapping("/queryPageSql") + public R> queryPageSql(@RequestBody SysDatabaseLinkBo bo) { + return R.ok(sysDatabaseLinkService.queryPageSql(bo)); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDatabaseLinkBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDatabaseLinkBo.java index 9fd07d1a..02d386cb 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDatabaseLinkBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDatabaseLinkBo.java @@ -90,5 +90,19 @@ public class SysDatabaseLinkBo extends BaseEntity { */ private String remark; + /** + * 分页大小 + */ + private Integer pageSize; + + /** + * 当前页数 + */ + private Integer pageNum; + + /** + * 查询SQL + */ + private String sql; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDatabaseLinkService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDatabaseLinkService.java index aeda3879..82d57f06 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDatabaseLinkService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDatabaseLinkService.java @@ -92,4 +92,10 @@ public interface ISysDatabaseLinkService { * 执行自定义SQL查询,返回数据List */ List> querySql(Long linkId, String sql); + + /** + * 执行分页自定义SQL查询,返回数据List + */ + Map queryPageSql(SysDatabaseLinkBo bo); + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDatabaseLinkServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDatabaseLinkServiceImpl.java index 6e18f699..a8074de7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDatabaseLinkServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDatabaseLinkServiceImpl.java @@ -341,4 +341,138 @@ public class SysDatabaseLinkServiceImpl implements ISysDatabaseLinkService { } return resultList; } + + /** + * 执行分页自定义SQL查询,返回数据List + */ + @Override + public Map queryPageSql(SysDatabaseLinkBo bo) { + Long linkId = bo.getLinkId(); + String sql = bo.getSql(); + Integer pageNum = bo.getPageNum(); + Integer pageSize = bo.getPageSize(); + + // 参数校验 + if (pageNum == null || pageNum < 1) { + pageNum = 1; + } + if (pageSize == null || pageSize < 1) { + pageSize = 10; + } + + // SQL校验 + String sqlTrim = sql.trim().toLowerCase(Locale.ROOT); + if (!(sqlTrim.startsWith("select") || sqlTrim.startsWith("with"))) { + throw new RuntimeException("只允许执行查询(SELECT/CTE)语句!"); + } + + // 获取数据库连接信息 + SysDatabaseLink link = baseMapper.selectById(linkId); + if (link == null) { + throw new RuntimeException("数据库连接信息不存在"); + } + + String url = link.getJdbcUrl(); + String username = link.getUsername(); + String password = link.getPassword(); + String driverClass = link.getDriverClass(); + + List> resultList = new ArrayList<>(); + long total = 0; + + try { + Class.forName(driverClass); + + // 获取数据库类型 + String dbType = getDatabaseType(url); + + // 构建分页SQL + String pageSql = buildPageSql(sql, pageNum, pageSize, dbType); + String countSql = buildCountSql(sql, dbType); + + try (Connection conn = DriverManager.getConnection(url, username, password); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(pageSql)) { + + // 获取分页数据 + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + + while (rs.next()) { + LinkedHashMap row = new LinkedHashMap<>(); + for (int i = 1; i <= columnCount; i++) { + row.put(metaData.getColumnLabel(i), rs.getObject(i)); + } + resultList.add(row); + } + + // 获取总记录数 + try (ResultSet countRs = stmt.executeQuery(countSql)) { + if (countRs.next()) { + total = countRs.getLong(1); + } + } + } + } catch (Exception e) { + throw new RuntimeException("SQL执行失败: " + e.getMessage(), e); + } + + // 构建分页结果 + Map result = new LinkedHashMap<>(); + result.put("rows", resultList); + result.put("total", total); + result.put("pageNum", pageNum); + result.put("pageSize", pageSize); + result.put("pages", (int) Math.ceil((double) total / pageSize)); + + return result; + } + + /** + * 根据数据库类型构建分页SQL + */ + private String buildPageSql(String originalSql, int pageNum, int pageSize, String dbType) { + int offset = (pageNum - 1) * pageSize; + + switch (dbType.toLowerCase()) { + case "mysql": + return originalSql + " LIMIT " + offset + "," + pageSize; + case "oracle": + return "SELECT * FROM (SELECT a.*, ROWNUM rn FROM (" + originalSql + + ") a WHERE ROWNUM <= " + (offset + pageSize) + ") WHERE rn > " + offset; + case "postgresql": + case "sqlserver": + return originalSql + " OFFSET " + offset + " ROWS FETCH NEXT " + pageSize + " ROWS ONLY"; + default: + throw new RuntimeException("不支持的数据库类型: " + dbType); + } + } + + /** + * 构建计数SQL + */ + private String buildCountSql(String originalSql, String dbType) { + // 移除原有ORDER BY子句(计数查询不需要排序) + String sqlWithoutOrder = originalSql.replaceAll("(?i)\\s+ORDER\\s+BY\\s+[^)]+$", ""); + return "SELECT COUNT(1) FROM (" + sqlWithoutOrder + ") temp_count_table"; + } + + /** + * 从JDBC URL识别数据库类型 + */ + private String getDatabaseType(String jdbcUrl) { + if (jdbcUrl.contains(":mysql:")) { + return "mysql"; + } else if (jdbcUrl.contains(":oracle:")) { + return "oracle"; + } else if (jdbcUrl.contains(":postgresql:")) { + return "postgresql"; + } else if (jdbcUrl.contains(":sqlserver:") || jdbcUrl.contains(":microsoft:")) { + return "sqlserver"; + } else { + throw new RuntimeException("无法识别的数据库类型: " + jdbcUrl); + } + } + + }