Java實現(xiàn)動態(tài)數(shù)據(jù)源切換的實踐指南
1、簡述
在 Java 開發(fā)中,許多場景需要訪問多個數(shù)據(jù)庫,例如多租戶系統(tǒng)或讀寫分離架構(gòu)。為了靈活高效地管理這些場景,動態(tài)數(shù)據(jù)源切換(Dynamic-DataSource) 技術(shù)應(yīng)運(yùn)而生。
本文介紹如何在 Spring Boot 項目中集成 Dynamic-DataSource 并實現(xiàn)動態(tài)切換功能,最后通過示例演示實際應(yīng)用。
2、什么是 Dynamic-DataSource?
Dynamic-DataSource 是一種可以根據(jù)業(yè)務(wù)需求動態(tài)切換數(shù)據(jù)源的技術(shù)。常見的使用場景包括:
- 讀寫分離:讀請求路由到只讀數(shù)據(jù)源,寫請求路由到主數(shù)據(jù)源。
- 多租戶系統(tǒng):根據(jù)租戶 ID 動態(tài)選擇數(shù)據(jù)庫。
- 分庫分表:根據(jù)分片鍵路由到對應(yīng)的數(shù)據(jù)源。
通過動態(tài)數(shù)據(jù)源切換,可以避免手動管理多個 DataSource,提升開發(fā)效率。Dynamic-DataSource 基于 Spring 的 AbstractRoutingDataSource 實現(xiàn)。核心思想是:
- 定義多個數(shù)據(jù)源(如主庫和從庫)。
- 使用線程上下文(ThreadLocal)保存當(dāng)前使用的數(shù)據(jù)源標(biāo)識。
- 根據(jù)上下文動態(tài)選擇數(shù)據(jù)源。
3、集成 Dynamic-DataSource
dynamic-datasource-spring-boot-starter 是一個基于springboot的快速集成多數(shù)據(jù)源的啟動器。
- 支持 數(shù)據(jù)源分組 ,適用于多種場景 純粹多庫 讀寫分離 一主多從 混合模式。
- 支持?jǐn)?shù)據(jù)庫敏感配置信息 加密(可自定義) ENC()。
- 支持每個數(shù)據(jù)庫獨(dú)立初始化表結(jié)構(gòu)schema和數(shù)據(jù)庫database。
- 支持無數(shù)據(jù)源啟動,支持懶加載數(shù)據(jù)源(需要的時候再創(chuàng)建連接)。
- 提供并簡化對Druid,HikariCp,BeeCp,Dbcp2的快速集成。
提供對Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等組件的集成方案。
3.1 Maven引用
在使用 Dynamic-DataSource之前,需要添加其依賴。以下是 Dynamic-DataSource的 Maven 依賴:
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
3.2 配置多數(shù)據(jù)源
在 application.yml 文件中配置多個數(shù)據(jù)源:
server:
port: 9001
spring:
datasource:
dynamic:
primary: master
strict: false
datasource:
master:
url: jdbc:mysql://192.168.25.181:3306/shop_admin?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
slave_1:
url: jdbc:mysql://192.168.25.181:3306/slave_db?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
3.3 編寫動態(tài)數(shù)據(jù)源切換邏輯
Dynamic-DataSource Starter 提供了注解和 AOP 的支持,可以簡化數(shù)據(jù)源切換邏輯。在需要動態(tài)切換數(shù)據(jù)源的地方添加 @DS 注解:
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lm.shop.shopeureka.entry.SysUserEntity;
import com.lm.shop.shopeureka.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserService extends ServiceImpl<SysUserMapper, SysUserEntity> {
@Resource
private SysUserMapper sysUserMapper;
@DS("master")
public void insertUser(SysUserEntity user) {
sysUserMapper.insert(user);
}
@DS("slave_1")
public SysUserEntity getUserById(Long id){
return sysUserMapper.selectById(id);
}
}
SysUserMapper:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lm.shop.shopeureka.entry.SysUserEntity;
public interface SysUserMapper extends BaseMapper<SysUserEntity> {
}
SysUserEntity:
package com.lm.shop.shopeureka.entry;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("sys_user")
public class SysUserEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用戶ID
*/
@TableId(value = "user_id")
private Long userId;
/**
* 用戶名
*/
@TableField("username")
private String username;
/**
* 密碼
*/
@TableField("password")
private String password;
/**
* 鹽
*/
@TableField("salt")
private String salt;
/**
* 郵箱
*/
@TableField("email")
private String email;
/**
* 手機(jī)號
*/
@TableField("mobile")
private String mobile;
/**
* 狀態(tài) 0:禁用 1:正常
*/
@TableField("status")
private Integer status;
/**
* 創(chuàng)建者ID
*/
@TableField("create_user_id")
private Long createUserId;
/**
* 創(chuàng)建時間
*/
@TableField("create_time")
private Date createTime;
}
在Controller控制層添加測試用例:
import com.lm.shop.shopeureka.entry.SysUserEntity;
import com.lm.shop.shopeureka.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/getUserById")
public SysUserEntity getUserById(@RequestParam Long id) {
return userService.getUserById(id);
}
@GetMapping("/insert")
public SysUserEntity insert(@RequestParam Long id) {
SysUserEntity sysUserEntity = new SysUserEntity();
sysUserEntity.setEmail("admin@admin.com");
sysUserEntity.setPassword("123456");
sysUserEntity.setUsername("adminMaster");
sysUserEntity.setCreateTime(new Date());
userService.insertUser(sysUserEntity);
return sysUserEntity;
}
}
在啟動類中添加mapper映射路徑:
@SpringBootApplication
@MapperScan("com.lm.shop.shopeureka.mapper")
public class ShopEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(ShopEurekaApplication.class, args);
}
}
4、總結(jié)
Dynamic-DataSource 提供了一種高效、簡潔的多數(shù)據(jù)源管理方式,非常適合多租戶系統(tǒng)、讀寫分離等復(fù)雜場景。本文通過配置和實際案例展示了如何集成和使用 Dynamic-DataSource,幫助開發(fā)者快速實現(xiàn)動態(tài)數(shù)據(jù)源切換功能。
通過動態(tài)數(shù)據(jù)源技術(shù),可以顯著提高系統(tǒng)的靈活性和擴(kuò)展性。如果你的項目中涉及多個數(shù)據(jù)庫的管理,Dynamic-DataSource 將是一個強(qiáng)大的工具。
以上就是Java實現(xiàn)動態(tài)數(shù)據(jù)源切換的實踐指南的詳細(xì)內(nèi)容,更多關(guān)于Java動態(tài)數(shù)據(jù)源切換的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring整合Quartz Job以及Spring Task的實現(xiàn)方法
下面小編就為大家分享一篇Spring整合Quartz Job以及Spring Task的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12

