In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "what is the process of SpringBoot multi-data source configuration". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Next, let the editor take you to learn "what is the process of SpringBoot multi-data source configuration"?
Preface
The core of multiple data sources is to inject AbstractRoutingDataSource into the IOC container and how to switch data sources. The way of injection can be to register BeanDefinition or build Bean, and the way to switch data sources can be method parameters or annotation switching (others are not imagined), depending on the requirements.
My requirement is to count the data of multiple databases and write the results to another database. The number of databases to be counted is variable, which cannot be directly injected through @ Bean. It is also a statistical task, and the switching of annotations in the DAO layer cannot be met, so I choose to register (AbstractRoutingDataSource) BeanDefinition and switch method parameters to achieve. Let's take the statistics of Chinese, Japanese and Korean users to the result database as an example.
Configuration file
Master is the result database, and other databases are counted (china and japan can be uniquely identified by enumeration, of course, you can also use String):
Dynamic: dataSources: master: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/result?useUnicode=true&characterEncoding=utf8xxxxxxxx username: root password: 123456 china: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/china?useUnicode=true&characterEncoding=utf8xxxxxxxx username: root password: 123456 japan: driver-class-name: com. Mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/japan?useUnicode=true&characterEncoding=utf8xxxxxxxx username: root password: 123456 korea: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/korea?useUnicode=true&characterEncoding=utf8xxxxxxxx username: root password: 123456
Corresponding configuration class:
Package com.statistics.dynamicds.core.config;import com.statistics.dynamicds.core.Country;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;import java.util.Map;import static com.statistics.dynamicds.core.config.MultiDataSourceProperties.PREFIX;@Data@Configuration@ConfigurationProperties (prefix = PREFIX) public class MultiDataSourceProperties {public static final String PREFIX = "dynamic"; private Map dataSources; @ Data public static class DataSourceProperties {private String driverClassName; private String url; private String username Private String password;}} package com.statistics.dynamicds.core;public enum Country {MASTER ("master", 0), CHINA ("china", 86), JAPAN ("japan", 81), KOREA ("korea", 82), / / other countries omit private final String name; private final int id; Country (String name, int id) {this.name = name; this.id = id;} public int getId () {return id } public String getName () {return name;}} dependency
The version of JPA,SpringBoot used by ORM is 2.3.7.RELEASE, and GetSet is simplified through Lombok.
Org.springframework.boot spring-boot-starter-data-jpa org.projectlombok lombok 1.18.22 provided to build AbstractRoutingDataSource
The dynamic data source of Spring needs to be injected into AbstractRoutingDataSource, because the statistical data source in the configuration file is not fixed, so it cannot be injected through the @ Bean annotation and needs to be built manually.
Add @ Import (MultiDataSourceImportBeanDefinitionRegistrar.class) to the startup class.
Add @ Import (MultiDataSourceImportBeanDefinitionRegistrar.class) to the startup class.
To add @ Import (MultiDataSourceImportBeanDefinitionRegistrar.class) to the startup class, write three lines of important things.
Package com.statistics.dynamicds.autoconfig;import com.statistics.dynamicds.core.DynamicDataSourceRouter;import com.statistics.dynamicds.core.Country;import com.statistics.dynamicds.core.config.MultiDataSourceProperties;import com.zaxxer.hikari.HikariDataSource;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.boot.context.properties.bind.Binder;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.EnvironmentAware Import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;import org.springframework.core.env.Environment;import org.springframework.core.type.AnnotationMetadata;import javax.annotation.Nonnull;import java.util.Map;import java.util.stream.Collectors;import static com.statistics.dynamicds.core.config.MultiDataSourceProperties.PREFIX;public class MultiDataSourceImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {public static final String DATASOURCE_BEANNAME = "dynamicDataSourceRouter"; private Environment environment @ Override public void registerBeanDefinitions (@ Nonnull AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {MultiDataSourceProperties multiDataSourceProperties = Binder.get (environment) .bind (PREFIX, MultiDataSourceProperties.class) .orElseThrow (()-> new RuntimeException ("no found dynamicds config")); final HikariDataSource [] defaultTargetDataSource = {null} Map targetDataSources = multiDataSourceProperties.getDataSources (). EntrySet (). Stream (). Collectors.toMap (Map.Entry::getKey, entry-> {MultiDataSourceProperties.DataSourceProperties dataSourceProperties = entry.getValue () HikariDataSource dataSource = DataSourceBuilder.create () .type (HikariDataSource.class) .driverClassName (dataSourceProperties.getDriverClassName ()) .url (dataSourceProperties.getUrl ()) .username (dataSourceProperties.getUsername ()) .password (dataSourceProperties.getPassword ()) .build () DataSource.setPoolName ("HikariPool-" + entry.getKey ()); if (Country.MASTER = = entry.getKey ()) {defaultTargetDataSource [0] = dataSource;} return dataSource;})) AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition (DynamicDataSourceRouter.class) .addConstructor ArgValue (defaultTargetDataSource [0]) .addConstructor ArgValue (targetDataSources) .getBeanDefinition (); registry.registerBeanDefinition (DATASOURCE_BEANNAME, beanDefinition); @ Override public void setEnvironment (@ Nonnull Environment environment) {this.environment = environment;}}
The MultiDataSourceProperties in the above code is not obtained by @ Resource or @ Autowired because ImportBeanDefinitionRegistrar is executed very early, and the configuration parameter class of @ ConfigurationProperties has not been injected yet, so you have to obtain it manually (add the @ ConfigurationProperties annotation to enable other Bean in the IOC container to obtain the configured Country, so as to switch data sources).
The following is the implementation class DynamicDataSourceRouter of AbstractRoutingDataSource:
Package com.statistics.dynamicds.core;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import java.util.Map;public class DynamicDataSourceRouter extends AbstractRoutingDataSource {public DynamicDataSourceRouter (Object defaultTargetDataSource, Map targetDataSources) {this.setDefaultTargetDataSource (defaultTargetDataSource); this.setTargetDataSources (targetDataSources);} @ Override protected Object determineCurrentLookupKey () {return DataSourceContextHolder.getLookupKey ();}} data source switching
The switching of the data source is controlled by DataSourceContextHolder and section DynamicDataSourceAspect:
Package com.statistics.dynamicds.core;public class DataSourceContextHolder {private static final ThreadLocal HOLDER = ThreadLocal.withInitial (()-> Country.MASTER); public static void setLookupKey (Country lookUpKey) {HOLDER.set (lookUpKey);} public static Country getLookupKey () {return HOLDER.get ();} public static void clear () {HOLDER.remove ();}} package com.statistics.dynamicds.core;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around Import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Aspect@Componentpublic class DynamicDataSourceAspect {@ Pointcut ("execution (* com.statistics.dao..*.* (..)") Void aspect () {} @ Around ("aspect ()") public Object around (ProceedingJoinPoint joinPoint) throws Throwable {for (Object arg: joinPoint.getArgs ()) {if (arg instanceof Country) {DataSourceContextHolder.setLookupKey ((Country) arg); break;}} try {return joinPoint.proceed ();} finally {DataSourceContextHolder.clear () At this point, I believe you have a deeper understanding of "what is the process of SpringBoot multi-data source configuration". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.