javascript
SpringBoot项目实现多数据源的三种方式
在開發過程中,我們經常被要求在一個項目中使用多數據源下面是總結下,使用多數據源的幾種方式:
方式一:在同一實例下的不同數據庫(在寫SQL的時候用(數據庫名稱+"."+表名))
方式二:AOP+注解實多數據源
方式三:使用dynamic-datasource-spring-boot-starter實現多數據源
方式一:不用對程序做任何更改,只是寫SQL時加上表名稱
上面是在同一實例下面的不同數據庫(citex_guess,citex_fusion),我先在一個項目中同時操作這兩個數據庫怎么半辦啦!
select * from citex_fusion.fusion_invitee limit 10 select * from citex_guess.guess_account limit 10不論是增刪改查,只要是對數據庫表進行操作,都需要加上表名
方式二、三、四通用實體類,mapper,service、web層
@Data public class GuessAccount {private Long id;private Integer userId;private Integer currencyId;private String currency;private BigDecimal availableQty;private BigDecimal frozenQty;private Date createTime;private Date updateTime; } @Data public class FusionInvite {private Integer userId;private Integer inviteeId;private String code;private Date createTime;private Date updateTime;}Mapper代碼
@Mapper public interface FusionMapper {@DS("master")@Select("select * from fusion_invitee limit 10 ")List<FusionInvite> getFusionInviteList();} @Mapper public interface GuessMapper {@DS("slaveOne")@Select("select * from guess_account limit 10")List<GuessAccount> getGuessAccountList();}service層
@Service public class TestService {@Autowiredprivate FusionMapper fusionMapper;@Autowiredprivate GuessMapper guessMapper;public Object testDynamic() {List<FusionInvite> fusionInviteList = getFusionInviteList();List<GuessAccount> guessAccountList = getGuessAccountList();ResultVos resultVos = new ResultVos();resultVos.setFusionList(fusionInviteList);resultVos.setGuessList(guessAccountList);return resultVos; }public List<FusionInvite> getFusionInviteList(){List<FusionInvite> fusionList= fusionMapper.getFusionInviteList();return fusionList;}public List<GuessAccount> getGuessAccountList(){List<GuessAccount> guessList=guessMapper.getGuessAccountList();return guessList;}web層
@RestController public class TestController {@Autowiredprivate TestService testService;@PostMapping("getList")public Object getTestList() {return testService.testDynamic();} }方式二:
Maven依賴:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.BUILD-SNAPSHOT</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>study_demo2</artifactId><version>0.0.1-SNAPSHOT</version><name>study_demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.8</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency></dependencies>配置文件YML
server:port: 8025spring:application:name: study_demo2datasource:master:username: jackpassword: jack987driver-class-name: com.mysql.jdbc.Driverjdbc-url: jdbc:mysql://127.0.0.1:3306/citex_fusion?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTCslave1:username: jackpassword: jack987driver-class-name: com.mysql.jdbc.Driverjdbc-url: jdbc:mysql://127.0.0.1:3306/citex_guess?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTCdruid:initial-size: 5max-active: 20min-idle: 5test-on-borrow: truemax-wait: -1min-evictable-idle-time-millis: 30000max-evictable-idle-time-millis: 30000time-between-eviction-runs-millis: 0 mybatis:configuration:map-underscore-to-camel-case: true多數據源配置類:
數據源切換注解類:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.METHOD}) @Documented public @interface DS {String value() default "master";}動態數據源配置類:
@Configuration public class DynamicDataSourceConfiguration {@Primary@Bean(name = "master")@ConfigurationProperties(prefix = "spring.datasource.master")public DataSource masterDataSource() {DataSource ds = DataSourceBuilder.create().build();return ds;}@Bean(name = "slaveOne")@ConfigurationProperties(prefix = "spring.datasource.slave1")public DataSource slave_1_DataSource() {DataSource ds = DataSourceBuilder.create().build();return ds;}/*** 動態數據源: 通過AOP在不同數據源之間動態切換** @return*/@Bean(name = "dynamicDataSource")public DataSource dataSource(@Autowired @Qualifier("master") DataSource primery, @Autowired @Qualifier("slaveOne") DataSource coocon) {DynamicDataSource dynamicDataSource = new DynamicDataSource();// 默認數據源dynamicDataSource.setDefaultTargetDataSource(primery);// 配置多數據源Map<Object, Object> dsMap = new HashMap<Object, Object>(2);dsMap.put("master", primery);dsMap.put("slaveOne", coocon);dynamicDataSource.setTargetDataSources(dsMap);return dynamicDataSource;}@Beanpublic PlatformTransactionManager txManager(DataSource dynamicDataSource) {return new DataSourceTransactionManager(dynamicDataSource);}@Bean@ConfigurationProperties(prefix = "mybatis")public SqlSessionFactoryBean sqlSessionFactoryBean(@Autowired @Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dynamicDataSource);return sqlSessionFactoryBean;}}實現多數據源的核心類(可動態路由的數據源類型)
public class DynamicDataSource extends AbstractRoutingDataSource {public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getDateSoureType();}public DynamicDataSource() {// TODO Auto-generated constructor stub} }使用ThreadLocal維護數據源類
@Slf4j public class DynamicDataSourceContextHolder { /*** 使用ThreadLocal維護變量,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,* 所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();/*** 設置數據源的變量*/public static void setDateSoureType(String dsType) {log.info("切換到{}數據源", dsType);CONTEXT_HOLDER.set(dsType);}/*** 獲得數據源的變量*/public static String getDateSoureType() {return CONTEXT_HOLDER.get();}/*** 清空數據源變量*/public static void clearDateSoureType() {CONTEXT_HOLDER.remove();}}切面攔截注解實現多數據源切換
@Aspect @Component @Slf4j public class DataSourceAspect {@Pointcut("@annotation(com.example.study.config.DS)")public void dataSourcePointCut() {}@Around("dataSourcePointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();DS annotation = method.getAnnotation(DS.class);DynamicDataSourceContextHolder.setDateSoureType(annotation.value());try {return point.proceed();} finally {// 銷毀數據源 在執行方法之后log.info("銷毀數據源{}", annotation.value());DynamicDataSourceContextHolder.clearDateSoureType();}}}以上是通過AOP切換數據源的配置類:
使用通用以上通用的實體類,Mapper、Service、web層便可以實現多數據源的使用。
方式三:使用dynamic-datasource-spring-boot-starter實現多數據源
maven依賴:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.BUILD-SNAPSHOT</version><relativePath/> <!-- lookup parent from repository --> </parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>2.3.2</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.8</version></dependency>配置文件(yml)
spring:application:name: study_demodatasource:dynamic:druid:initial-size: 5max-active: 20min-idle: 5test-on-borrow: truemax-wait: -1min-evictable-idle-time-millis: 30000max-evictable-idle-time-millis: 30000time-between-eviction-runs-millis: 0primary: master #設置默認的數據源或者數據源組,默認值即為masterdatasource:master:username: jackpassword: jack987driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/citex_fusion?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTCslaveOne:username: jackpassword: jack987driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/citex_guess?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTC mybatis:configuration:map-underscore-to-camel-case: true測試地址:localhost:8080/getList
結果:
總結
以上是生活随笔為你收集整理的SpringBoot项目实现多数据源的三种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php问答系统模板,tipask问答系统
- 下一篇: JS执行上下文