├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── inspur │ │ └── dynamicdatasource │ │ ├── DynamicDatasourceApplication.java │ │ ├── config │ │ ├── DynamicDataSource.java │ │ ├── DynamicDataSourceConfig.java │ │ ├── SpringContextHolder.java │ │ ├── annotation │ │ │ └── DynamicSwitchDataSource.java │ │ └── aspect │ │ │ └── DataSourceAspect.java │ │ ├── controller │ │ └── UserController.java │ │ ├── entity │ │ ├── DatabaseDetail.java │ │ └── User.java │ │ ├── mapper │ │ ├── DatabaseDetailMapper.java │ │ └── UserMapper.java │ │ └── service │ │ └── UserService.java └── resources │ └── application.yml └── test └── java └── com └── inspur └── dynamicdatasource ├── DynamicDatasourceApplicationTests.java └── datatest ├── DatabaseTest.java └── UserServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.5"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShangYao/dynamic-datasource/de2d4029e0053891080268c93b8b29e0459b8a0d/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dynamic-datasource 2 | ####业务描述: 3 | 每新增一个租户,就新建一个数据库,不同的租户的数据,会存储到各自的数据库中 4 | 5 | 不同的租户的请求需要操作各自对应的数据库。 6 | 7 | ####问题点 8 | 1. 多数据源 9 | 2. 数据源与租户的对应关系(数据库动态获取租户的数据源信息) 10 | 3. 如何区分不同用户的请求(session) 11 | 12 | 13 | 多租户业务下,根据租户id动态创建、切换数据源 14 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.0.RELEASE 9 | 10 | 11 | com.inspur 12 | dynamic-datasource 13 | 0.0.1-SNAPSHOT 14 | dynamic-datasource 15 | Demo project for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | com.baomidou 24 | mybatis-plus-boot-starter 25 | 3.2.0 26 | 27 | 28 | mysql 29 | mysql-connector-java 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | org.projectlombok 39 | lombok 40 | true 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-aop 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-web 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-test 53 | test 54 | 55 | 56 | org.junit.vintage 57 | junit-vintage-engine 58 | 59 | 60 | 61 | 62 | junit 63 | junit 64 | test 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-maven-plugin 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/DynamicDatasourceApplication.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 7 | 8 | @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) 9 | @MapperScan("com.inspur.dynamicdatasource.mapper") 10 | public class DynamicDatasourceApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(DynamicDatasourceApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/config/DynamicDataSource.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.config; 2 | 3 | import com.inspur.dynamicdatasource.entity.DatabaseDetail; 4 | import com.inspur.dynamicdatasource.mapper.DatabaseDetailMapper; 5 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 6 | 7 | import javax.sql.DataSource; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public class DynamicDataSource extends AbstractRoutingDataSource { 11 | 12 | /** 13 | * 缓存当前线程数据源的key(租户id) 14 | */ 15 | private static final ThreadLocal CURRENT_DATASOURCE_KEY = new ThreadLocal<>(); 16 | /** 17 | * 缓存租户对应的数据源 18 | * ConcurrentHashMap<租户id,数据源> 19 | */ 20 | private ConcurrentHashMap targetDataSources = new ConcurrentHashMap<>(); 21 | 22 | private DatabaseDetailMapper databaseDetailMapper = null; 23 | 24 | public DynamicDataSource(DataSource defaultTargetDataSource) { 25 | super.setDefaultTargetDataSource(defaultTargetDataSource); 26 | super.setTargetDataSources(targetDataSources); 27 | } 28 | 29 | /** 30 | * 选择当前线程数据源的key 31 | */ 32 | @Override 33 | public Object determineCurrentLookupKey() { 34 | return CURRENT_DATASOURCE_KEY.get(); 35 | } 36 | 37 | /** 38 | * 清除当前线程数据源key 39 | */ 40 | public static void clearCurrentDataSourceKey() { 41 | CURRENT_DATASOURCE_KEY.remove(); 42 | } 43 | 44 | /** 45 | * 设置当前线程的数据源 46 | */ 47 | public void setCurrentThreadDataSource(String dataSourceKey) { 48 | if (!targetDataSources.containsKey(dataSourceKey)) { 49 | addNewDataSource(dataSourceKey); 50 | } 51 | CURRENT_DATASOURCE_KEY.set(dataSourceKey); 52 | } 53 | 54 | private synchronized void addNewDataSource(String dataSourceKey) { 55 | if (targetDataSources.containsKey(dataSourceKey)) { 56 | return; 57 | } 58 | DataSource datasource = createDataSource(dataSourceKey); 59 | targetDataSources.put(dataSourceKey, datasource); 60 | super.afterPropertiesSet(); 61 | } 62 | 63 | 64 | private DataSource createDataSource(String dataSourceKey) { 65 | DatabaseDetail dbDetail = getDatabaseDetail(dataSourceKey); 66 | return DynamicDataSourceConfig.createDataSource(dbDetail); 67 | } 68 | 69 | // 数据库信息动态获取 70 | private DatabaseDetail getDatabaseDetail(String dataSourceKey) { 71 | if (null == databaseDetailMapper) { 72 | getDatabaseDetailMapper(); 73 | } 74 | return databaseDetailMapper.selectOneByTenantId(dataSourceKey); 75 | } 76 | 77 | private synchronized void getDatabaseDetailMapper() { 78 | if (null == databaseDetailMapper) { 79 | databaseDetailMapper = SpringContextHolder.getBean(DatabaseDetailMapper.class); 80 | } 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/config/DynamicDataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.config; 2 | 3 | import com.inspur.dynamicdatasource.entity.DatabaseDetail; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.jdbc.DataSourceBuilder; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Primary; 9 | 10 | import javax.sql.DataSource; 11 | 12 | @Configuration 13 | public class DynamicDataSourceConfig { 14 | 15 | @Value("${dynamic-datasource.default.url}") 16 | private String defaultUrl; 17 | @Value("${dynamic-datasource.default.driverClassName}") 18 | private String driverClassName; 19 | @Value("${dynamic-datasource.default.username}") 20 | private String defaultUsername; 21 | @Value("${dynamic-datasource.default.password}") 22 | private String defaultPassword; 23 | 24 | @Bean("defaultDataSource") 25 | public DataSource defaultDataSource() { 26 | return DataSourceBuilder.create().url(defaultUrl) 27 | .driverClassName(driverClassName) 28 | .username(defaultUsername) 29 | .password(defaultPassword).build(); 30 | } 31 | 32 | @Bean 33 | @Primary 34 | public DynamicDataSource dynamicDataSource(DataSource defaultDataSource) { 35 | return new DynamicDataSource(defaultDataSource); 36 | } 37 | 38 | static DataSource createDataSource(DatabaseDetail dbDetail) { 39 | return DataSourceBuilder.create().url(dbDetail.getUrl()) 40 | .driverClassName(dbDetail.getDriverClassName()) 41 | .username(dbDetail.getUsername()) 42 | .password(dbDetail.getPassword()).build(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/config/SpringContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.config; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class SpringContextHolder implements ApplicationContextAware { 10 | private static ApplicationContext APP_CONTEXT = null; 11 | 12 | @Override 13 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 14 | APP_CONTEXT = applicationContext; 15 | } 16 | 17 | static T getBean(Class requiredType) { 18 | return APP_CONTEXT.getBean(requiredType); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/config/annotation/DynamicSwitchDataSource.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.config.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 根据session中的租户id,动态切换数据源,无租户id时,使用默认数据源 7 | */ 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface DynamicSwitchDataSource { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/config/aspect/DataSourceAspect.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.config.aspect; 2 | 3 | import com.inspur.dynamicdatasource.config.DynamicDataSource; 4 | import org.aspectj.lang.annotation.*; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | 9 | @Aspect 10 | @Component 11 | public class DataSourceAspect { 12 | 13 | @Autowired 14 | private DynamicDataSource dynamicDataSource; 15 | 16 | /** 17 | * 切换数据源应发生在事务之前,否则仍然会使用默认数据源, 18 | * 故数据源切换放在controller层(默认事务应放到service层) 19 | */ 20 | //@Pointcut("@annotation(com.inspur.dynamicdatasource.config.annotation.DynamicSwitchDataSource)") 21 | @Pointcut("execution(public * com.inspur.dynamicdatasource.controller..*.*(..))") 22 | public void dataSourcePointCut() { 23 | } 24 | 25 | @Before("dataSourcePointCut()") 26 | public void beforeExecute() { 27 | String tenantId = getTenantIdFromSession(); 28 | if (tenantId != null) { 29 | dynamicDataSource.setCurrentThreadDataSource(tenantId); 30 | } 31 | 32 | } 33 | 34 | @After("dataSourcePointCut()") 35 | public void afterExecute() { 36 | DynamicDataSource.clearCurrentDataSourceKey(); 37 | } 38 | 39 | //TODO 从session中获取租客id 40 | private String getTenantIdFromSession() { 41 | return "2"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.controller; 2 | 3 | import com.inspur.dynamicdatasource.entity.User; 4 | import com.inspur.dynamicdatasource.service.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | import java.util.List; 9 | 10 | @RestController 11 | public class UserController { 12 | 13 | @Autowired 14 | private UserService userService; 15 | 16 | @GetMapping("/user") 17 | public List getAll() { 18 | return userService.selectAll(); 19 | } 20 | 21 | @PostMapping("/user") 22 | public int insertOne(User user) { 23 | try { 24 | return userService.insert(user); 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | } 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/entity/DatabaseDetail.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DatabaseDetail { 7 | private long id; 8 | private String tenantId; 9 | private String url; 10 | private String username; 11 | private String password; 12 | private String driverClassName; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.KeySequence; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | @Data 10 | @TableName("user") 11 | @KeySequence("seq_user") 12 | public class User { 13 | 14 | @TableId(value = "id",type = IdType.INPUT) 15 | private Long id; 16 | private String name; 17 | private String tenantId; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/mapper/DatabaseDetailMapper.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.inspur.dynamicdatasource.entity.DatabaseDetail; 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | public interface DatabaseDetailMapper extends BaseMapper { 8 | 9 | @Select("select * from database_detail where tenant_id=#{tenantId} limit 1 ") 10 | DatabaseDetail selectOneByTenantId(String tenantId); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.inspur.dynamicdatasource.entity.User; 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | import java.util.List; 8 | 9 | public interface UserMapper extends BaseMapper { 10 | 11 | @Select("select * from user") 12 | List selectAll(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/inspur/dynamicdatasource/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.service; 2 | 3 | import com.inspur.dynamicdatasource.entity.User; 4 | import com.inspur.dynamicdatasource.mapper.UserMapper; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | 11 | @Service 12 | public class UserService { 13 | 14 | @Resource 15 | private UserMapper userMapper; 16 | 17 | @Transactional(rollbackFor = Exception.class) 18 | public List selectAll() { 19 | return userMapper.selectAll(); 20 | } 21 | 22 | @Transactional(rollbackFor = Exception.class) 23 | public int insert(User user) throws Exception { 24 | int flag = userMapper.insert(user); 25 | // int e=4/0; 26 | return flag; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | dynamic-datasource: 3 | default: 4 | url: jdbc:mysql://localhost:3306/tenant001?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC 5 | username: root 6 | password: root 7 | driverClassName: com.mysql.cj.jdbc.Driver 8 | 9 | #mybatis-plus配置控制台打印完整带参数SQL语句 10 | mybatis-plus: 11 | configuration: 12 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 13 | -------------------------------------------------------------------------------- /src/test/java/com/inspur/dynamicdatasource/DynamicDatasourceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DynamicDatasourceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/inspur/dynamicdatasource/datatest/DatabaseTest.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.datatest; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.jdbc.DataSourceBuilder; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | import javax.sql.DataSource; 12 | import java.sql.Connection; 13 | import java.sql.SQLException; 14 | import java.sql.Statement; 15 | 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class DatabaseTest { 19 | @Autowired 20 | DataSource defaultDataSource; 21 | 22 | @Test 23 | public void testCreatDB() throws SQLException { 24 | Connection con = defaultDataSource.getConnection(); 25 | Statement sta = con.createStatement(); 26 | String createSql = "CREATE TABLE people(" 27 | + "name varchar(10) not null," 28 | + "age int(4) not null" 29 | + ")charset=utf8;"; 30 | // System.out.println(sta.executeLargeUpdate(createSql)); 31 | con.close(); 32 | sta.close(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/inspur/dynamicdatasource/datatest/UserServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.inspur.dynamicdatasource.datatest; 2 | 3 | import com.inspur.dynamicdatasource.entity.User; 4 | import com.inspur.dynamicdatasource.service.UserService; 5 | import org.junit.Test; 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | @RunWith(SpringRunner.class) 13 | @SpringBootTest 14 | public class UserServiceTest { 15 | @Autowired 16 | private UserService userService; 17 | 18 | @Test 19 | public void testSelectAll() { 20 | userService.selectAll().forEach(System.out::println); 21 | } 22 | 23 | @Test 24 | public void testInsert() throws Exception { 25 | User user = new User(); 26 | user.setName("jet"); 27 | user.setTenantId("3"); 28 | Assertions.assertEquals(1, userService.insert(user)); 29 | } 30 | } 31 | --------------------------------------------------------------------------------