Files
ledgerly-docs/dev/database.md
T

2.4 KiB
Raw Blame History

动态数据源

系统支持在服务启动之后再配置数据库,并可在 SQLite 与 MySQL 之间运行时切换,无需启动前准备。

设计目标

  • 未配置数据库时应用仍能正常启动,前端引导进入初始化页面。
  • 支持 SQLite(本地单文件)与 MySQL 两种数据库。
  • 保存配置后立即生效并自动建表,无需手动执行 SQL。

核心组件

组件 职责
DynamicDataSource 继承 AbstractRoutingDataSource,维护目标数据源映射,切换时重建解析缓存并关闭旧连接池
DataSourceContextHolder 保存当前数据源 key 与类型;未配置时使用 UNCONFIGURED 占位
UnconfiguredDataSource 占位数据源,任何取连接操作抛「数据库未配置」(业务码 5031)
DatabaseConfig / DatabaseConfigStore 配置模型与持久化(config/database.json)
SchemaInitializer 按类型执行 init.sql(MySQL)或 schema-sqlite.sql(SQLite),幂等建表
SchemaMigrator 建表后的幂等结构迁移(如列重命名),启动与切换数据源时执行
DatabaseBootstrap 应用启动后加载配置并初始化

FinanceApplication 刻意排除了 DataSourceAutoConfiguration,以便「零配置也能启动」。

配置来源与顺序

  1. 优先读取本地 config/database.json。
  2. 若无本地配置但存在环境变量 DB_URL / DB_USERNAME / DB_PASSWORD,则作为首次配置并保存。

保存流程为:创建并测试新数据源 → 建表 → 结构迁移 → 先落盘再切换,确保切换失败时可回退。

连接池策略

  • SQLite:连接池固定为 1,避免文件锁冲突。
  • MySQL:最大 10、最小 2。

MySQL 的 JDBC URL 会自动附带 UTF-8、关闭 SSL、Asia/Shanghai 时区与 createDatabaseIfNotExist=true。

跨库方言适配

统计模块依据 DataSourceContextHolder.getType() 选择时间分组函数:

  • MySQL:DATE_FORMAT / QUARTER
  • SQLite:strftime

切换行为

登录后可在「系统设置 → 数据库配置」随时切换数据库。切换后原数据库的数据保留,不做自动迁移。

切换成功后会清空进程内的用户偏好缓存(见整体架构),避免读到旧库的数据。

相关文档