Add unit tests for dynamic-datasource-spring-boot3-starter
(#552)
This commit is contained in:
parent
bc747fad91
commit
18b5312b68
67
.github/workflows/ci.yml
vendored
Normal file
67
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- '.github/workflows/ci.yml'
|
||||
- '**/pom.xml'
|
||||
- '**/src/main/**'
|
||||
- '**/src/test/**'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- '.github/workflows/ci.yml'
|
||||
- '**/pom.xml'
|
||||
- '**/src/main/**'
|
||||
- '**/src/test/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
MAVEN_OPTS: -Dhttps.protocols=TLSv1.2 -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true
|
||||
|
||||
jobs:
|
||||
test-maximum-jdk-ci:
|
||||
name: Test CI - JDK ${{ matrix.java-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
java-version: [ '17' ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.java-version }}
|
||||
cache: 'maven'
|
||||
- name: Build test with Maven
|
||||
run: |
|
||||
./mvnw -am -pl dynamic-datasource-spring-boot3-starter -T1C -B clean test
|
||||
test-minimum-jdk-ci:
|
||||
name: Test CI - JDK ${{ matrix.java-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
java-version: [ '8' ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.java-version }}
|
||||
cache: 'maven'
|
||||
- name: Build test with Maven
|
||||
run: |
|
||||
./mvnw -am -pl dynamic-datasource-creator -T1C -B clean package
|
||||
./mvnw -am -pl dynamic-datasource-spring -T1C -B clean package
|
||||
./mvnw -am -pl dynamic-datasource-spring-boot-common -T1C -B clean package
|
||||
./mvnw -am -pl dynamic-datasource-spring-boot-starter -T1C -B clean package
|
@ -21,7 +21,7 @@
|
||||
<img src="https://img.shields.io/:license-apache-brightgreen.svg" >
|
||||
</a>
|
||||
<a>
|
||||
<img src="https://img.shields.io/badge/JDK-1.7+-green.svg" >
|
||||
<img src="https://img.shields.io/badge/JDK-8+-green.svg" >
|
||||
</a>
|
||||
<a>
|
||||
<img src="https://img.shields.io/badge/springBoot-1.5.x__2.x.x__3.x.x-green.svg" >
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
<java.version>17</java.version>
|
||||
<spring-boot-dependencies.version>3.1.1</spring-boot-dependencies.version>
|
||||
</properties>
|
||||
|
||||
@ -41,6 +41,17 @@
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.hikaricp.HikariCpConfig;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@SpringBootTest(classes = AddRemoveDatasourceApplication.class, webEnvironment = RANDOM_PORT)
|
||||
public class AddRemoveDatasourceTest {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
DefaultDataSourceCreator dataSourceCreator;
|
||||
|
||||
@Test
|
||||
void testAddAndRemoveDataSource() {
|
||||
HikariCpConfig hikariCpConfig = new HikariCpConfig();
|
||||
hikariCpConfig.setConnectionTestQuery("select 1");
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
dataSourceProperty.setHikari(hikariCpConfig);
|
||||
dataSourceProperty.setPoolName("slave_1");
|
||||
dataSourceProperty.setUsername("sa");
|
||||
dataSourceProperty.setPassword("");
|
||||
dataSourceProperty.setType(SimpleDriverDataSource.class);
|
||||
dataSourceProperty.setUrl("jdbc:h2:mem:test1;MODE=MySQL");
|
||||
dataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
ds.addDataSource(dataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(dataSourceProperty));
|
||||
assertThat(ds.getDataSources().keySet()).contains("slave_1");
|
||||
ds.removeDataSource("slave_1");
|
||||
assertThat(ds.getDataSources().keySet()).doesNotContain("slave_1");
|
||||
}
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
class AddRemoveDatasourceApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AddRemoveDatasourceApplication.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@SpringBootTest(classes = LoadDatasourceFromJDBCApplication.class, webEnvironment = RANDOM_PORT)
|
||||
public class LoadDatasourceFromJDBCTest {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Test
|
||||
void testExistDataSource() {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
assertThat(ds.getDataSources().keySet()).contains("master", "db1", "db2", "db3");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"})
|
||||
@SpringBootApplication
|
||||
class LoadDatasourceFromJDBCApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LoadDatasourceFromJDBCApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider(DefaultDataSourceCreator dataSourceCreator) {
|
||||
return new AbstractJdbcDataSourceProvider(dataSourceCreator, "org.h2.Driver", "jdbc:h2:mem:test;MODE=MySQL", "sa", "") {
|
||||
@Override
|
||||
protected Map<String, DataSourceProperty> executeStmt(Statement statement) throws SQLException {
|
||||
statement.execute("""
|
||||
CREATE TABLE IF NOT EXISTS `DB`
|
||||
(
|
||||
`name` VARCHAR(30) NULL DEFAULT NULL,
|
||||
`username` VARCHAR(30) NULL DEFAULT NULL,
|
||||
`password` VARCHAR(30) NULL DEFAULT NULL,
|
||||
`url` VARCHAR(30) NULL DEFAULT NULL,
|
||||
`driver` VARCHAR(30) NULL DEFAULT NULL
|
||||
)""");
|
||||
statement.executeUpdate("insert into DB values ('master','sa','','jdbc:h2:mem:test;MODE=MySQL','org.h2.Driver')");
|
||||
statement.executeUpdate("insert into DB values ('db1','sa','','jdbc:h2:mem:test2','org.h2.Driver')");
|
||||
statement.executeUpdate("insert into DB values ('db2','sa','','jdbc:h2:mem:test3','org.h2.Driver')");
|
||||
statement.executeUpdate("insert into DB values ('db3','sa','','jdbc:h2:mem:test4','org.h2.Driver')");
|
||||
Map<String, DataSourceProperty> map = new HashMap<>();
|
||||
ResultSet rs = statement.executeQuery("select * from DB");
|
||||
while (rs.next()) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
dataSourceProperty.setUsername(rs.getString("username"));
|
||||
dataSourceProperty.setPassword(rs.getString("password"));
|
||||
dataSourceProperty.setUrl(rs.getString("url"));
|
||||
dataSourceProperty.setDriverClassName(rs.getString("driver"));
|
||||
dataSourceProperty.setType(SimpleDriverDataSource.class);
|
||||
map.put(rs.getString("name"), dataSourceProperty);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.fixture.service.nest.*;
|
||||
import org.h2.tools.Server;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@SpringBootTest(classes = NestApplication.class, webEnvironment = RANDOM_PORT)
|
||||
public class NestDataSourceTest {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
DefaultDataSourceCreator dataSourceCreator;
|
||||
|
||||
@Autowired
|
||||
TeacherService teacherService;
|
||||
|
||||
@Autowired
|
||||
StudentService studentService;
|
||||
|
||||
@Autowired
|
||||
SchoolService schoolService;
|
||||
|
||||
@Test
|
||||
void testNest() {
|
||||
DataSourceProperty masterDataSourceProperty = new DataSourceProperty();
|
||||
masterDataSourceProperty.setPoolName("master");
|
||||
masterDataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
masterDataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/add-remove-datasource.sql'");
|
||||
masterDataSourceProperty.setUsername("sa");
|
||||
masterDataSourceProperty.setPassword("");
|
||||
DataSourceProperty teacherDataSourceProperty = new DataSourceProperty();
|
||||
teacherDataSourceProperty.setPoolName("teacher");
|
||||
teacherDataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
teacherDataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/add-remove-datasource.sql'");
|
||||
teacherDataSourceProperty.setUsername("sa");
|
||||
teacherDataSourceProperty.setPassword("");
|
||||
DataSourceProperty studentDataSourceProperty = new DataSourceProperty();
|
||||
studentDataSourceProperty.setPoolName("student");
|
||||
studentDataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
studentDataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/add-remove-datasource.sql'");
|
||||
studentDataSourceProperty.setUsername("sa");
|
||||
studentDataSourceProperty.setPassword("");
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
ds.addDataSource(masterDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(masterDataSourceProperty));
|
||||
ds.addDataSource(teacherDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(teacherDataSourceProperty));
|
||||
ds.addDataSource(studentDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(studentDataSourceProperty));
|
||||
assertThat(ds.getDataSources().keySet()).contains("master", "teacher", "student");
|
||||
assertThat(teacherService.addTeacherWithTx("ss", 1)).isEqualTo(1);
|
||||
assertThat(studentService.addStudentWithTx("tt", 2)).isEqualTo(1);
|
||||
assertThat(teacherService.selectTeachers()).isEqualTo(List.of(new Teacher(1, "tt", 2)));
|
||||
assertThat(studentService.selectStudents()).isEqualTo(List.of(new Student(1, "tt", 2)));
|
||||
assertThat(schoolService.addTeacherAndStudentWithTx()).isEqualTo(2);
|
||||
assertThat(teacherService.selectTeachers()).isEqualTo(List.of(new Teacher(1, "tt", 2), new Teacher(2, "bb", 4)));
|
||||
assertThat(studentService.selectStudents()).isEqualTo(List.of(new Student(1, "tt", 2), new Student(2, "bb", 4)));
|
||||
}
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
class NestApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(NestApplication.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.fixture.service.spel.User;
|
||||
import com.baomidou.dynamic.datasource.fixture.service.spel.UserService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
|
||||
|
||||
@SpringBootTest(classes = SPELApplication.class, webEnvironment = RANDOM_PORT)
|
||||
public class SPELTest {
|
||||
|
||||
MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
DefaultDataSourceCreator dataSourceCreator;
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
@BeforeEach
|
||||
void setup(WebApplicationContext webApplicationContext) {
|
||||
this.mockMvc = webAppContextSetup(webApplicationContext).defaultResponseCharacterEncoding(StandardCharsets.UTF_8).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSPEL() {
|
||||
DataSourceProperty masterDataSourceProperty = new DataSourceProperty();
|
||||
masterDataSourceProperty.setPoolName("master");
|
||||
masterDataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
masterDataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/spring-expression-language.sql'");
|
||||
masterDataSourceProperty.setUsername("sa");
|
||||
masterDataSourceProperty.setPassword("");
|
||||
DataSourceProperty tenant1_1DataSourceProperty = new DataSourceProperty();
|
||||
tenant1_1DataSourceProperty.setPoolName("tenant1_1");
|
||||
tenant1_1DataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
tenant1_1DataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/spring-expression-language.sql'");
|
||||
tenant1_1DataSourceProperty.setUsername("sa");
|
||||
tenant1_1DataSourceProperty.setPassword("");
|
||||
DataSourceProperty tenant1_2DataSourceProperty = new DataSourceProperty();
|
||||
tenant1_2DataSourceProperty.setPoolName("tenant1_2");
|
||||
tenant1_2DataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
tenant1_2DataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/spring-expression-language.sql'");
|
||||
tenant1_2DataSourceProperty.setUsername("sa");
|
||||
tenant1_2DataSourceProperty.setPassword("");
|
||||
DataSourceProperty tenant2_1DataSourceProperty = new DataSourceProperty();
|
||||
tenant2_1DataSourceProperty.setPoolName("tenant2_1");
|
||||
tenant2_1DataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
tenant2_1DataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/spring-expression-language.sql'");
|
||||
tenant2_1DataSourceProperty.setUsername("sa");
|
||||
tenant2_1DataSourceProperty.setPassword("");
|
||||
DataSourceProperty tenant2_2DataSourceProperty = new DataSourceProperty();
|
||||
tenant2_2DataSourceProperty.setPoolName("tenant2_2");
|
||||
tenant2_2DataSourceProperty.setDriverClassName("org.h2.Driver");
|
||||
tenant2_2DataSourceProperty.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE");
|
||||
tenant2_2DataSourceProperty.setUsername("sa");
|
||||
tenant2_2DataSourceProperty.setPassword("");
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
ds.addDataSource(masterDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(masterDataSourceProperty));
|
||||
ds.addDataSource(tenant1_1DataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(tenant1_1DataSourceProperty));
|
||||
ds.addDataSource(tenant1_2DataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(tenant1_2DataSourceProperty));
|
||||
ds.addDataSource(tenant2_1DataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(tenant2_1DataSourceProperty));
|
||||
ds.addDataSource(tenant2_2DataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(tenant2_2DataSourceProperty));
|
||||
assertThat(ds.getDataSources().keySet()).contains("master", "tenant1_1", "tenant1_2", "tenant2_1", "tenant2_2");
|
||||
assertDoesNotThrow(() -> {
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/users/session").characterEncoding(StandardCharsets.UTF_8))
|
||||
.andDo(print()).andExpectAll(
|
||||
status().isOk(),
|
||||
content().encoding(StandardCharsets.UTF_8)
|
||||
).andReturn().getResponse().getContentAsString();
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/users/header").contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("tenantName", "tenant1")
|
||||
.characterEncoding(StandardCharsets.UTF_8)
|
||||
).andDo(print()).andExpectAll(
|
||||
status().isOk(),
|
||||
content().encoding(StandardCharsets.UTF_8)
|
||||
).andReturn().getResponse().getContentAsString();
|
||||
});
|
||||
assertThat(userService.selectSpelByKey("tenant1")).isEqualTo("tenant1");
|
||||
assertThat(userService.selecSpelByTenant(new User("tenant2"))).isEqualTo("tenant2");
|
||||
}
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
class SPELApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SPELApplication.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.controller;
|
||||
|
||||
import com.baomidou.dynamic.datasource.fixture.service.spel.User;
|
||||
import com.baomidou.dynamic.datasource.fixture.service.spel.UserService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
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.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RequestMapping("/users")
|
||||
@RestController
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@GetMapping("/session")
|
||||
public List<User> session(HttpServletRequest request) {
|
||||
request.getSession().setAttribute("tenantName", "tenant1");
|
||||
return userService.selectSpelBySession();
|
||||
}
|
||||
|
||||
@GetMapping("/header")
|
||||
public String header() {
|
||||
userService.selectSpelByHeader();
|
||||
return "success";
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.nest;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class SchoolService {
|
||||
private final TeacherService teacherService;
|
||||
private final StudentService studentService;
|
||||
|
||||
public SchoolService(TeacherService teacherService, StudentService studentService) {
|
||||
this.teacherService = teacherService;
|
||||
this.studentService = studentService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int addTeacherAndStudentWithTx() {
|
||||
int aa = teacherService.addTeacherNoTx("aa", 3);
|
||||
int bb = studentService.addStudentNoTx("bb", 4);
|
||||
return aa + bb;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.nest;
|
||||
|
||||
public record Student(Integer id, String name, Integer age) {
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.nest;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"})
|
||||
@Service
|
||||
@DS("student")
|
||||
public class StudentService {
|
||||
private final DataSource dataSource;
|
||||
|
||||
public StudentService(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int addStudentWithTx(String name, Integer age) {
|
||||
try (Connection connection = dataSource.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("insert into student (name,age) values (?,?)")) {
|
||||
preparedStatement.setString(1, name);
|
||||
preparedStatement.setInt(2, age);
|
||||
return preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int addStudentNoTx(String name, Integer age) {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("insert into student (name,age) values (?,?)")) {
|
||||
preparedStatement.setString(1, name);
|
||||
preparedStatement.setInt(2, age);
|
||||
return preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Student> selectStudents() {
|
||||
List<Student> result = new LinkedList<>();
|
||||
try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) {
|
||||
ResultSet resultSet = statement.executeQuery("SELECT * FROM student");
|
||||
while (resultSet.next()) {
|
||||
result.add(new Student(resultSet.getInt(1), resultSet.getString(2), resultSet.getInt(3)));
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.nest;
|
||||
|
||||
public record Teacher(Integer id, String name, Integer age) {
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.nest;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"SqlNoDataSourceInspection", "SqlDialectInspection"})
|
||||
@Service
|
||||
@DS("teacher")
|
||||
public class TeacherService {
|
||||
private final DataSource dataSource;
|
||||
|
||||
public TeacherService(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int addTeacherWithTx(String name, Integer age) {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("insert into teacher (name,age) values (?,?)")) {
|
||||
preparedStatement.setString(1, name);
|
||||
preparedStatement.setInt(2, age);
|
||||
return preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int addTeacherNoTx(String name, Integer age) {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("insert into teacher (name,age) values (?,?)")) {
|
||||
preparedStatement.setString(1, name);
|
||||
preparedStatement.setInt(2, age);
|
||||
return preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Teacher> selectTeachers() {
|
||||
List<Teacher> result = new LinkedList<>();
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
ResultSet resultSet = statement.executeQuery("SELECT * FROM student");
|
||||
while (resultSet.next()) {
|
||||
result.add(new Teacher(resultSet.getInt(1), resultSet.getString(2), resultSet.getInt(3)));
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.spel;
|
||||
|
||||
public record User(Integer id, String name, Integer age, String tenantName) {
|
||||
public User(String tenantName) {
|
||||
this(null, null, null, tenantName);
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright © 2018 organization baomidou
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.fixture.service.spel;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection", "UnusedReturnValue", "unused"})
|
||||
@Service
|
||||
@DS("slave")
|
||||
public class UserService {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
public UserService(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
|
||||
@DS("#session.tenantName")
|
||||
public List<User> selectSpelBySession() {
|
||||
List<User> result = new LinkedList<>();
|
||||
try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) {
|
||||
ResultSet resultSet = statement.executeQuery("select * from t_user");
|
||||
while (resultSet.next()) {
|
||||
result.add(new User(resultSet.getInt(1), resultSet.getString(2), resultSet.getInt(3), resultSet.getString(4)));
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@DS("#header.tenantName")
|
||||
public List<User> selectSpelByHeader() {
|
||||
List<User> result = new LinkedList<>();
|
||||
try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) {
|
||||
ResultSet resultSet = statement.executeQuery("select * from t_user");
|
||||
while (resultSet.next()) {
|
||||
result.add(new User(resultSet.getInt(1), resultSet.getString(2), resultSet.getInt(3), resultSet.getString(4)));
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@DS("#tenantName")
|
||||
public String selectSpelByKey(String tenantName) {
|
||||
return DynamicDataSourceContextHolder.peek();
|
||||
|
||||
}
|
||||
|
||||
@DS("#user.tenantName")
|
||||
public String selecSpelByTenant(User user) {
|
||||
return DynamicDataSourceContextHolder.peek();
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
CREATE TABLE IF NOT EXISTS TEACHER
|
||||
(
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(30) NULL DEFAULT NULL,
|
||||
age INT(11) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS STUDENT
|
||||
(
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(30) NULL DEFAULT NULL,
|
||||
age INT(11) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS t_user
|
||||
(
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(30) NULL DEFAULT NULL,
|
||||
age INT(11) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
6
pom.xml
6
pom.xml
@ -60,6 +60,7 @@
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<seata.version>1.4.2</seata.version>
|
||||
<lombok.version>1.18.28</lombok.version>
|
||||
<h2.version>2.2.220</h2.version>
|
||||
|
||||
<maven-clean-plugin.version>3.3.1</maven-clean-plugin.version>
|
||||
<maven-install-plugin.version>3.1.1</maven-install-plugin.version>
|
||||
@ -165,6 +166,11 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user