|
|
|
|
@ -341,4 +341,138 @@ public class SysDatabaseLinkServiceImpl implements ISysDatabaseLinkService {
|
|
|
|
|
}
|
|
|
|
|
return resultList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 执行分页自定义SQL查询,返回数据List
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Map<String, Object> 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<LinkedHashMap<String, Object>> 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<String, Object> 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<String, Object> 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|