This commit is contained in:
2025-11-25 14:27:10 +08:00
parent d3931a9ddd
commit 7d8aeedcf2
23 changed files with 414 additions and 166 deletions

View File

@ -27,10 +27,10 @@ public class SQLiteUtil {
// 统一日期格式LocalDateTime
private static final DateTimeFormatter LOCAL_DATE_TIME_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// 连接池缓存key=数据库文件路径、value=DBCP2数据源支持多连接复用
// 连接池缓存: key=数据库文件路径、value=DBCP2数据源支持多连接复用
private static final Map<String, BasicDataSource> DATA_SOURCE_POOL = new ConcurrentHashMap<>();
// 字段缓存缓存类的字段映射(避免反射重复开销)
// 字段缓存: 缓存类的字段映射(避免反射重复开销)
private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();
@ -64,17 +64,17 @@ public class SQLiteUtil {
dataSource.setUrl("jdbc:sqlite:" + dbFilePath);
// 2. 连接池核心参数根据并发量调整、SQLite不建议过多连接
dataSource.setMaxTotal(30); // 最大连接数20-50根据服务器CPU/内存调整)
dataSource.setMaxIdle(15); // 最大空闲连接保留部分连接避免频繁创建
dataSource.setMinIdle(5); // 最小空闲连接保证基础并发响应速度
dataSource.setTimeBetweenEvictionRunsMillis(60000); // 连接检测间隔1分钟
dataSource.setMinEvictableIdleTimeMillis(300000); // 连接空闲超时5分钟清理长期空闲连接
dataSource.setMaxTotal(30); // 最大连接数: 20-50根据服务器CPU/内存调整)
dataSource.setMaxIdle(15); // 最大空闲连接: 保留部分连接避免频繁创建
dataSource.setMinIdle(5); // 最小空闲连接: 保证基础并发响应速度
dataSource.setTimeBetweenEvictionRunsMillis(60000); // 连接检测间隔: 1分钟
dataSource.setMinEvictableIdleTimeMillis(300000); // 连接空闲超时: 5分钟清理长期空闲连接
// 3. 连接有效性验证(避免使用失效连接)
dataSource.setTestOnBorrow(true); // 借连接时验证
dataSource.setTestOnReturn(false); // 还连接时不验证(减少开销)
dataSource.setValidationQuery("SELECT 1"); // 轻量验证SQLSQLite支持
dataSource.setValidationQueryTimeout(2); // 验证超时2秒
dataSource.setValidationQueryTimeout(2); // 验证超时: 2秒
// 4. PreparedStatement缓存减少SQL解析开销
dataSource.setPoolPreparedStatements(true);
@ -83,11 +83,11 @@ public class SQLiteUtil {
// 5. SQLite底层性能优化关键提升并发能力
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement()) {
stmt.execute("PRAGMA journal_mode=WAL;"); // 启用WAL模式支持多读者+单写者(核心优化)
stmt.execute("PRAGMA journal_mode=WAL;"); // 启用WAL模式: 支持多读者+单写者(核心优化)
stmt.execute("PRAGMA cache_size=-20000;"); // 页面缓存20MB负号表示KB单位、内存足可调大
stmt.execute("PRAGMA synchronous=NORMAL;"); // 同步级别平衡性能与安全崩溃最多丢WAL日志
stmt.execute("PRAGMA synchronous=NORMAL;"); // 同步级别: 平衡性能与安全崩溃最多丢WAL日志
stmt.execute("PRAGMA temp_store=MEMORY;"); // 临时表/索引存内存减少磁盘IO
stmt.execute("PRAGMA busy_timeout=2000;"); // 忙等待超时2秒避免瞬时并发锁等待
stmt.execute("PRAGMA busy_timeout=2000;"); // 忙等待超时: 2秒避免瞬时并发锁等待
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("请检查路径是否存在");
@ -108,7 +108,7 @@ public class SQLiteUtil {
try {
dataSource.close(); // DBCP2会自动关闭所有活跃/空闲连接
} catch (SQLException e) {
System.err.println("关闭SQLite数据源失败路径" + dbFilePath + "" + e.getMessage());
System.err.println("关闭SQLite数据源失败路径: " + dbFilePath + ": " + e.getMessage());
}
}
}
@ -121,7 +121,7 @@ public class SQLiteUtil {
try {
dataSource.close();
} catch (SQLException e) {
System.err.println("关闭SQLite数据源失败" + e.getMessage());
System.err.println("关闭SQLite数据源失败: " + e.getMessage());
}
}
// 清理缓存(避免内存泄漏)
@ -129,7 +129,7 @@ public class SQLiteUtil {
FIELD_CACHE.clear();
}
// JVM关闭钩子确保程序退出时释放所有数据源资源
// JVM关闭钩子: 确保程序退出时释放所有数据源资源
static {
Runtime.getRuntime().addShutdownHook(new Thread(SQLiteUtil::closeAllDataSources));
}
@ -138,7 +138,7 @@ public class SQLiteUtil {
// ========================== 数据查询核心方法 ==========================
/**
* 执行查询并返回单个对象(优化版连接池+字段缓存)
* 执行查询并返回单个对象(优化版: 连接池+字段缓存)
*
* @param dbFilePath 数据库路径
* @param sql 查询SQL
@ -152,7 +152,7 @@ public class SQLiteUtil {
}
/**
* 执行查询并返回对象列表(优化版预构建字段映射+资源自动回收)
* 执行查询并返回对象列表(优化版: 预构建字段映射+资源自动回收)
*
* @param dbFilePath 数据库路径
* @param sql 查询SQL
@ -169,7 +169,7 @@ public class SQLiteUtil {
// 预加载字段映射(缓存生效、避免重复反射)
Map<String, Field> fieldMap = getFieldMap(clazz);
// try-with-resources自动关闭Connection、PreparedStatement、ResultSet
// try-with-resources: 自动关闭Connection、PreparedStatement、ResultSet
try (Connection conn = getConnection(dbFilePath);
PreparedStatement pstmt = createPreparedStatement(conn, sql, params);
ResultSet rs = pstmt.executeQuery()) {
@ -193,20 +193,20 @@ public class SQLiteUtil {
resultList.add(obj);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
throw new SQLException("创建对象实例失败(类型" + clazz.getName() + "", e);
throw new SQLException("创建对象实例失败(类型: " + clazz.getName() + "", e);
}
}
} catch (SQLException e) {
// 异常时关闭当前数据源(避免后续请求使用异常连接)
closeDataSource(dbFilePath);
throw new SQLException("执行查询失败SQL" + sql + "", e);
throw new SQLException("执行查询失败SQL: " + sql + "", e);
}
return resultList;
}
/**
* 执行增删改SQL优化版连接池+自动提交)
* 执行增删改SQL优化版: 连接池+自动提交)
*
* @param dbFilePath 数据库路径
* @param sql 增删改SQL
@ -223,12 +223,12 @@ public class SQLiteUtil {
return pstmt.executeUpdate();
} catch (SQLException e) {
closeDataSource(dbFilePath);
throw new SQLException("执行增删改失败SQL" + sql + "", e);
throw new SQLException("执行增删改失败SQL: " + sql + "", e);
}
}
/**
* 执行计数查询(优化版轻量结果处理)
* 执行计数查询(优化版: 轻量结果处理)
*
* @param dbFilePath 数据库路径
* @param sql 计数SQL如SELECT COUNT(*) ...
@ -246,7 +246,7 @@ public class SQLiteUtil {
return rs.next() ? rs.getInt(1) : 0;
} catch (SQLException e) {
closeDataSource(dbFilePath);
throw new SQLException("执行计数查询失败SQL" + sql + "", e);
throw new SQLException("执行计数查询失败SQL: " + sql + "", e);
}
}
@ -270,12 +270,12 @@ public class SQLiteUtil {
pstmt.execute();
} catch (SQLException e) {
closeDataSource(dbFilePath);
throw new SQLException("执行DDL失败SQL" + sql + "、路径" + dbFilePath + "", e);
throw new SQLException("执行DDL失败SQL: " + sql + "、路径: " + dbFilePath + "", e);
}
}
/**
* 重载无参数的DDL执行
* 重载: 无参数的DDL执行
*/
public static void executeDDL(String dbFilePath, String sql) throws SQLException {
executeDDL(dbFilePath, sql, null);
@ -408,7 +408,7 @@ public class SQLiteUtil {
field.set(obj, convertedValue);
}
} catch (IllegalAccessException e) {
System.err.println("警告字段赋值失败(字段" + field.getName() + "、值类型" + value.getClass().getName() + "" + e.getMessage());
System.err.println("警告: 字段赋值失败(字段: " + field.getName() + "、值类型: " + value.getClass().getName() + ": " + e.getMessage());
}
}
@ -452,7 +452,7 @@ public class SQLiteUtil {
}
// 不支持的类型转换(打印警告)
System.err.println("警告不支持的类型转换(目标类型" + targetType.getName() + "、原始值类型" + value.getClass().getName() + "");
System.err.println("警告: 不支持的类型转换(目标类型: " + targetType.getName() + "、原始值类型: " + value.getClass().getName() + "");
return null;
}
@ -461,7 +461,7 @@ public class SQLiteUtil {
try {
return Integer.parseInt(value.trim());
} catch (NumberFormatException e) {
System.err.println("警告字符串转Integer失败" + value + "");
System.err.println("警告: 字符串转Integer失败: " + value + "");
return null;
}
}
@ -470,7 +470,7 @@ public class SQLiteUtil {
try {
return Long.parseLong(value.trim());
} catch (NumberFormatException e) {
System.err.println("警告字符串转Long失败" + value + "");
System.err.println("警告: 字符串转Long失败: " + value + "");
return null;
}
}
@ -479,7 +479,7 @@ public class SQLiteUtil {
try {
return Double.parseDouble(value.trim());
} catch (NumberFormatException e) {
System.err.println("警告字符串转Double失败" + value + "");
System.err.println("警告: 字符串转Double失败: " + value + "");
return null;
}
}
@ -489,7 +489,7 @@ public class SQLiteUtil {
try {
return LocalDateTime.parse((String) value, LOCAL_DATE_TIME_FORMATTER);
} catch (DateTimeParseException e) {
System.err.println("警告字符串转LocalDateTime失败" + value + "");
System.err.println("警告: 字符串转LocalDateTime失败: " + value + "");
return null;
}
} else if (value instanceof Timestamp) {
@ -513,7 +513,7 @@ public class SQLiteUtil {
try {
return blob.getBytes(1, (int) blob.length());
} catch (SQLException e) {
System.err.println("警告Blob转byte[]失败" + e.getMessage());
System.err.println("警告: Blob转byte[]失败: " + e.getMessage());
}
}
return null;