一、簡單上手:從配置到使用全流程
DsFactory 的核心優勢是零侵入配置,支持多種配置方式,不管是 properties 文件還是代碼里直接定義,都能快速初始化數據源。先引依賴(Maven):
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-db</artifactId><version>5.8.20</version>
</dependency>
<!-- 數據庫驅動根據需要添加,比如MySQL -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>
- 配置文件方式:最推薦的做法在resources目錄下創建db.setting文件,配置數據源信息:
在resources目錄下創建db.setting文件,配置數據源信息:
# 默認數據源(必填)
[default]
url = jdbc:mysql://localhost:3306/db1
username = root
password=123456
driver = com.mysql.cj.jdbc.Driver# 第二個數據源(名稱自定義)
[second]
url = jdbc:mysql://localhost:3306/db2
username = root
password=123456
driver = com.mysql.cj.jdbc.Driver# 連接池配置(可選,全局生效)
[pool]
maxActive = 50
maxIdle = 10
minIdle = 5
initialSize = 5
然后一行代碼獲取數據源:
// 獲取默認數據源
DataSource defaultDs = DsFactory.get();// 獲取指定名稱的數據源
DataSource secondDs = DsFactory.get("second");
- 代碼配置方式:動態添加數據源
不需要配置文件時,直接在代碼里定義:
// 創建數據源配置
DbConfig defaultConfig = new DbConfig();
defaultConfig.setUrl("jdbc:mysql://localhost:3306/db1");
defaultConfig.setUsername("root");
defaultConfig.setPassword("123456");// 添加到DsFactory
DsFactory.register("default", defaultConfig);// 再添加一個數據源
DbConfig otherConfig = new DbConfig();
otherConfig.setUrl("jdbc:mysql://localhost:3306/db3");
otherConfig.setUsername("root");
otherConfig.setPassword("123456");
DsFactory.register("other", otherConfig);// 使用時直接獲取
DataSource defaultDs = DsFactory.get("default");
DataSource otherDs = DsFactory.get("other");
- 支持的數據庫類型:不止關系型數據庫
除了 MySQL、Oracle 這些關系型數據庫,還支持 SQLite、H2 等嵌入式數據庫:
# SQLite數據源配置
[sqlite]
url = jdbc:sqlite:test.db
driver = org.sqlite.JDBC
# SQLite不需要用戶名密碼
甚至可以配置 Redis(雖然 Redis 不是數據庫,但 DsFactory 也能管理):
[redis]
type = redis
host = localhost
port = 6379
password =
二、核心功能:數據源管理就該這么簡單
- 切換數據源:一行代碼搞定
需要操作不同數據庫時,直接通過名稱獲取即可:
// 操作默認數據庫
Db.use(DsFactory.get()).query("select * from user");// 切換到second數據源
Db.use(DsFactory.get("second")).execute("insert into log values(...)");
在業務代碼中切換更是方便:
public class UserService {public List<User> getUsersFromDb1() {// 使用默認數據源return Db.use(DsFactory.get()).query(Entity.create("user"), User.class);}public List<User> getUsersFromDb2() {// 切換到第二個數據源return Db.use(DsFactory.get("second")).query(Entity.create("user"), User.class);}
}
- 連接池配置:全局統一管理
在db.setting的[pool]節點配置連接池參數,所有數據源都會生效:
[pool]
maxActive = 100 # 最大活躍連接數
maxIdle = 20 # 最大空閑連接數
minIdle = 5 # 最小空閑連接數
initialSize = 10 # 初始連接數
maxWait = 3000 # 獲取連接的最大等待時間(毫秒)
如果某個數據源需要特殊配置,可以單獨指定:
# 單獨給second數據源配置連接池
[second]
url = jdbc:mysql://localhost:3306/db2
username = root
password = 123456
driver = com.mysql.cj.jdbc.Driver
maxActive = 80 # 覆蓋全局配置
maxIdle = 15
- 動態增減數據源:運行時也能改
支持在程序運行中添加或移除數據源,適合動態切換場景:
// 動態添加一個臨時數據源
DbConfig tempConfig = new DbConfig();
tempConfig.setUrl("jdbc:mysql://localhost:3306/temp_db");
tempConfig.setUsername("root");
tempConfig.setPassword("123456");
DsFactory.register("temp", tempConfig);// 使用臨時數據源
Db.use(DsFactory.get("temp")).execute("create table temp_table(id int)");// 用完移除
DsFactory.unregister("temp");
三、實戰場景
- 讀寫分離:查詢走從庫,寫入走主庫
配置主庫和從庫兩個數據源,業務代碼中按需切換:
# db.setting配置
[master]
url = jdbc:mysql://master:3306/db
username = root
password = 123456[slave]
url = jdbc:mysql://slave:3306/db
username = root
password = 123456
業務代碼:
public class OrderService {// 寫入操作走主庫public void createOrder(Order order) {Db.use(DsFactory.get("master")).insert(Entity.parse(order));}// 查詢操作走從庫public List<Order> getOrders(Long userId) {Entity where = Entity.create("order").set("user_id", userId);return Db.use(DsFactory.get("slave")).query(where, Order.class);}
}
- 多租戶系統:不同租戶用不同數據庫
給每個租戶分配獨立數據庫,通過租戶 ID 切換數據源:
public class TenantService {// 根據租戶ID獲取數據源private DataSource getTenantDs(String tenantId) {// 檢查是否已注冊該租戶數據源if (!DsFactory.contains(tenantId)) {// 從配置中心獲取租戶數據庫信息(實際項目中從配置中心獲取)String url = "jdbc:mysql://localhost:3306/tenant_" + tenantId;DbConfig config = new DbConfig();config.setUrl(url);config.setUsername("root");config.setPassword("123456");// 注冊數據源DsFactory.register(tenantId, config);}return DsFactory.get(tenantId);}// 操作租戶數據public List<User> getTenantUsers(String tenantId) {return Db.use(getTenantDs(tenantId)).query(Entity.create("user"), User.class);}
}
- 臨時數據處理:動態創建數據源
處理臨時任務時,動態創建數據源,用完即刪:
public class TempDataService {public void processTempData(String dbPath) {// 動態注冊SQLite數據源String dsName = "temp_" + System.currentTimeMillis();DbConfig config = new DbConfig();config.setUrl("jdbc:sqlite:" + dbPath);config.setDriver("org.sqlite.JDBC");DsFactory.register(dsName, config);try {// 處理數據Db.use(DsFactory.get(dsName)).execute("select * from temp_data");} finally {// 移除數據源DsFactory.unregister(dsName);}}
}
四、優勢
-
配置簡單:一個db.setting文件搞定所有數據源,不用寫 XML
-
切換方便:通過名稱獲取數據源,一行代碼完成切換,不用 AOP
-
支持廣泛:各種關系型數據庫、嵌入式數據庫都能管理
-
動態靈活:運行時可以添加、移除數據源,適合動態場景
當然它也有局限:復雜的分庫分表場景還是需要 Sharding-JDBC,但普通多數據源場景用它足夠了。
五、細節注意
-
默認數據源必須有:至少要配置一個default數據源,否則會報錯
-
驅動包要配齊:使用哪種數據庫,就要添加對應的驅動依賴,不然會提示 “找不到驅動類”
-
連接池參數要合理:根據業務量調整maxActive等參數,避免連接數過多導致數據庫壓力過大