diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bcae819..967b5a3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
cache: 'maven'
- name: Build test with Maven
run: |
- ./mvnw -am -pl dynamic-datasource-spring-boot3-starter -T1C -B clean test
+ ./mvnw -T1C -B clean test
test-minimum-jdk-ci:
name: Test CI - JDK ${{ matrix.java-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
@@ -64,4 +64,4 @@ jobs:
./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
+ ./mvnw -am -pl dynamic-datasource-spring-boot-starter -T1C -B clean test
diff --git a/dynamic-datasource-spring-boot-starter/pom.xml b/dynamic-datasource-spring-boot-starter/pom.xml
index b04a52f..ca998bf 100644
--- a/dynamic-datasource-spring-boot-starter/pom.xml
+++ b/dynamic-datasource-spring-boot-starter/pom.xml
@@ -27,7 +27,6 @@
com.alibaba
druid-spring-boot-starter
- 1.2.18
true
@@ -35,6 +34,15 @@
spring-boot-configuration-processor
true
+
+ com.h2database
+ h2
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
-
-
\ No newline at end of file
+
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/AddRemoveDatasourceTest.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/AddRemoveDatasourceTest.java
new file mode 100644
index 0000000..4ee735e
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/AddRemoveDatasourceTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.Test;
+import org.junit.runner.RunWith;
+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 org.springframework.test.context.junit4.SpringRunner;
+
+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)
+@RunWith(SpringRunner.class)
+public class AddRemoveDatasourceTest {
+
+ @Autowired
+ DataSource dataSource;
+
+ @Autowired
+ DefaultDataSourceCreator dataSourceCreator;
+
+ @Test
+ public 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);
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/LoadDatasourceFromJDBCTest.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/LoadDatasourceFromJDBCTest.java
new file mode 100644
index 0000000..e884d28
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/LoadDatasourceFromJDBCTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.Test;
+import org.junit.runner.RunWith;
+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 org.springframework.test.context.junit4.SpringRunner;
+
+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)
+@RunWith(SpringRunner.class)
+public class LoadDatasourceFromJDBCTest {
+
+ @Autowired
+ DataSource dataSource;
+
+ @Test
+ public 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 executeStmt(Statement statement) throws SQLException {
+ statement.execute("CREATE TABLE IF NOT EXISTS `DB`\n" +
+ "(\n" +
+ " `name` VARCHAR(30) NULL DEFAULT NULL,\n" +
+ " `username` VARCHAR(30) NULL DEFAULT NULL,\n" +
+ " `password` VARCHAR(30) NULL DEFAULT NULL,\n" +
+ " `url` VARCHAR(30) NULL DEFAULT NULL,\n" +
+ " `driver` VARCHAR(30) NULL DEFAULT NULL\n" +
+ ")");
+ 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 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;
+ }
+ };
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java
new file mode 100644
index 0000000..64363d0
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java
@@ -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.SchoolService;
+import com.baomidou.dynamic.datasource.fixture.service.nest.Student;
+import com.baomidou.dynamic.datasource.fixture.service.nest.StudentService;
+import com.baomidou.dynamic.datasource.fixture.service.nest.Teacher;
+import com.baomidou.dynamic.datasource.fixture.service.nest.TeacherService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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.test.context.junit4.SpringRunner;
+
+import javax.sql.DataSource;
+import java.util.Arrays;
+import java.util.Collections;
+
+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)
+@RunWith(SpringRunner.class)
+public class NestDataSourceTest {
+
+ @Autowired
+ DataSource dataSource;
+
+ @Autowired
+ DefaultDataSourceCreator dataSourceCreator;
+
+ @Autowired
+ TeacherService teacherService;
+
+ @Autowired
+ StudentService studentService;
+
+ @Autowired
+ SchoolService schoolService;
+
+ @Test
+ public void testNest() {
+ DataSourceProperty masterDataSourceProperty = createDataSourceProperty("master");
+ DataSourceProperty teacherDataSourceProperty = createDataSourceProperty("teacher");
+ DataSourceProperty studentDataSourceProperty = createDataSourceProperty("student");
+ 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(Collections.singletonList(new Teacher(1, "tt", 2)));
+ assertThat(studentService.selectStudents()).isEqualTo(Collections.singletonList(new Student(1, "tt", 2)));
+ assertThat(schoolService.addTeacherAndStudentWithTx()).isEqualTo(2);
+ assertThat(teacherService.selectTeachers()).isEqualTo(Arrays.asList(new Teacher(1, "tt", 2), new Teacher(2, "bb", 4)));
+ assertThat(studentService.selectStudents()).isEqualTo(Arrays.asList(new Student(1, "tt", 2), new Student(2, "bb", 4)));
+ }
+
+ private DataSourceProperty createDataSourceProperty(String poolName) {
+ DataSourceProperty result = new DataSourceProperty();
+ result.setPoolName(poolName);
+ result.setDriverClassName("org.h2.Driver");
+ result.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/add-remove-datasource.sql'");
+ result.setUsername("sa");
+ result.setPassword("");
+ return result;
+ }
+}
+
+@SpringBootApplication
+class NestApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(NestApplication.class, args);
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java
new file mode 100644
index 0000000..82b1144
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.CustomResultHandler;
+import com.baomidou.dynamic.datasource.fixture.service.spel.User;
+import com.baomidou.dynamic.datasource.fixture.service.spel.UserService;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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.context.junit4.SpringRunner;
+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.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)
+@RunWith(SpringRunner.class)
+public class SPELTest {
+
+ MockMvc mockMvc;
+
+ @Autowired
+ private WebApplicationContext webApplicationContext;
+
+ @Autowired
+ DataSource dataSource;
+
+ @Autowired
+ DefaultDataSourceCreator dataSourceCreator;
+
+ @Autowired
+ UserService userService;
+
+ @Before
+ public void setup() {
+ this.mockMvc = webAppContextSetup(webApplicationContext)
+ .alwaysDo(new CustomResultHandler())
+ .build();
+ }
+
+ @Test
+ public void testSPEL() throws Exception {
+ DataSourceProperty masterDataSourceProperty = createDataSourceProperty("master");
+ DataSourceProperty tenant1_1DataSourceProperty = createDataSourceProperty("tenant1_1");
+ DataSourceProperty tenant1_2DataSourceProperty = createDataSourceProperty("tenant1_2");
+ DataSourceProperty tenant2_1DataSourceProperty = createDataSourceProperty("tenant2_1");
+ DataSourceProperty tenant2_2DataSourceProperty = createDataSourceProperty("tenant2_2");
+ 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");
+ mockMvc.perform(MockMvcRequestBuilders.get("/users/session").characterEncoding(StandardCharsets.UTF_8.name()))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().encoding(StandardCharsets.UTF_8.name()))
+ .andReturn().getResponse().getContentAsString();
+ mockMvc.perform(MockMvcRequestBuilders.get("/users/header").contentType(MediaType.APPLICATION_FORM_URLENCODED)
+ .header("tenantName", "tenant1")
+ .characterEncoding(StandardCharsets.UTF_8.name())
+ ).andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().encoding(StandardCharsets.UTF_8.name()))
+ .andReturn().getResponse().getContentAsString();
+ assertThat(userService.selectSpelByKey("tenant1")).isEqualTo("tenant1");
+ assertThat(userService.selecSpelByTenant(new User("tenant2"))).isEqualTo("tenant2");
+ }
+
+ private DataSourceProperty createDataSourceProperty(String poolName) {
+ DataSourceProperty result = new DataSourceProperty();
+ result.setPoolName(poolName);
+ result.setDriverClassName("org.h2.Driver");
+ result.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/spring-expression-language.sql'");
+ result.setUsername("sa");
+ result.setPassword("");
+ return result;
+ }
+}
+
+@SpringBootApplication
+class SPELApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SPELApplication.class, args);
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java
new file mode 100644
index 0000000..a5af057
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java
@@ -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 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 javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+@RequestMapping("/users")
+@RestController
+public class UserController {
+
+ @Autowired
+ private UserService userService;
+
+ @GetMapping("/session")
+ public List session(HttpServletRequest request) {
+ request.getSession().setAttribute("tenantName", "tenant1");
+ return userService.selectSpelBySession();
+ }
+
+ @GetMapping("/header")
+ public String header() {
+ userService.selectSpelByHeader();
+ return "success";
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java
new file mode 100644
index 0000000..3608bab
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java
@@ -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;
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/Student.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/Student.java
new file mode 100644
index 0000000..5a9e20b
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/Student.java
@@ -0,0 +1,27 @@
+/*
+ * 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 lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class Student {
+ private Integer id;
+ private String name;
+ private Integer age;
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java
new file mode 100644
index 0000000..53c4815
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java
@@ -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 selectStudents() {
+ List 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);
+ }
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/Teacher.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/Teacher.java
new file mode 100644
index 0000000..ec8b1a7
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/Teacher.java
@@ -0,0 +1,30 @@
+/*
+ * 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 lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class Teacher {
+
+ private Integer id;
+
+ private String name;
+
+ private Integer age;
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java
new file mode 100644
index 0000000..dda872f
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java
@@ -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 selectTeachers() {
+ List 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);
+ }
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/CustomResultHandler.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/CustomResultHandler.java
new file mode 100644
index 0000000..e707c91
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/CustomResultHandler.java
@@ -0,0 +1,13 @@
+package com.baomidou.dynamic.datasource.fixture.service.spel;
+
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultHandler;
+
+import java.nio.charset.StandardCharsets;
+
+public class CustomResultHandler implements ResultHandler {
+ @Override
+ public void handle(MvcResult result) {
+ result.getResponse().setCharacterEncoding(StandardCharsets.UTF_8.name());
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/User.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/User.java
new file mode 100644
index 0000000..f42a335
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/User.java
@@ -0,0 +1,39 @@
+/*
+ * 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 lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class User {
+
+ private Integer id;
+
+ private String name;
+
+ private Integer age;
+
+ private String tenantName;
+
+ public User(String tenantName) {
+ this.id = null;
+ this.name = null;
+ this.age = null;
+ this.tenantName = tenantName;
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/UserService.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/UserService.java
new file mode 100644
index 0000000..b00d496
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/spel/UserService.java
@@ -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 selectSpelBySession() {
+ List 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 selectSpelByHeader() {
+ List 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();
+ }
+}
diff --git a/dynamic-datasource-spring-boot-starter/src/test/resources/db/add-remove-datasource.sql b/dynamic-datasource-spring-boot-starter/src/test/resources/db/add-remove-datasource.sql
new file mode 100644
index 0000000..97e13ac
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/resources/db/add-remove-datasource.sql
@@ -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)
+);
diff --git a/dynamic-datasource-spring-boot-starter/src/test/resources/db/spring-expression-language.sql b/dynamic-datasource-spring-boot-starter/src/test/resources/db/spring-expression-language.sql
new file mode 100644
index 0000000..5f426ae
--- /dev/null
+++ b/dynamic-datasource-spring-boot-starter/src/test/resources/db/spring-expression-language.sql
@@ -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)
+);
diff --git a/dynamic-datasource-spring-boot3-starter/pom.xml b/dynamic-datasource-spring-boot3-starter/pom.xml
index 072677c..511d0cf 100644
--- a/dynamic-datasource-spring-boot3-starter/pom.xml
+++ b/dynamic-datasource-spring-boot3-starter/pom.xml
@@ -33,7 +33,6 @@
com.alibaba
druid-spring-boot-3-starter
- 1.2.18
true
@@ -44,7 +43,6 @@
com.h2database
h2
- ${h2.version}
test
diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java
index a052ffe..1350ce4 100644
--- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java
+++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/NestDataSourceTest.java
@@ -18,17 +18,18 @@ 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 com.baomidou.dynamic.datasource.fixture.service.nest.SchoolService;
+import com.baomidou.dynamic.datasource.fixture.service.nest.Student;
+import com.baomidou.dynamic.datasource.fixture.service.nest.StudentService;
+import com.baomidou.dynamic.datasource.fixture.service.nest.Teacher;
+import com.baomidou.dynamic.datasource.fixture.service.nest.TeacherService;
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;
@@ -54,24 +55,9 @@ public class NestDataSourceTest {
@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("");
+ DataSourceProperty masterDataSourceProperty = createDataSourceProperty("master");
+ DataSourceProperty teacherDataSourceProperty = createDataSourceProperty("teacher");
+ DataSourceProperty studentDataSourceProperty = createDataSourceProperty("student");
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
ds.addDataSource(masterDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(masterDataSourceProperty));
ds.addDataSource(teacherDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(teacherDataSourceProperty));
@@ -85,6 +71,16 @@ public class NestDataSourceTest {
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)));
}
+
+ private DataSourceProperty createDataSourceProperty(String poolName) {
+ DataSourceProperty result = new DataSourceProperty();
+ result.setPoolName(poolName);
+ result.setDriverClassName("org.h2.Driver");
+ result.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/add-remove-datasource.sql'");
+ result.setUsername("sa");
+ result.setPassword("");
+ return result;
+ }
}
@SpringBootApplication
diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java
index 490c10a..be067f8 100644
--- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java
+++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/SPELTest.java
@@ -63,36 +63,11 @@ public class SPELTest {
@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("");
+ DataSourceProperty masterDataSourceProperty = createDataSourceProperty("master");
+ DataSourceProperty tenant1_1DataSourceProperty = createDataSourceProperty("tenant1_1");
+ DataSourceProperty tenant1_2DataSourceProperty = createDataSourceProperty("tenant1_2");
+ DataSourceProperty tenant2_1DataSourceProperty = createDataSourceProperty("tenant2_1");
+ DataSourceProperty tenant2_2DataSourceProperty = createDataSourceProperty("tenant2_2");
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
ds.addDataSource(masterDataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(masterDataSourceProperty));
ds.addDataSource(tenant1_1DataSourceProperty.getPoolName(), dataSourceCreator.createDataSource(tenant1_1DataSourceProperty));
@@ -117,6 +92,16 @@ public class SPELTest {
assertThat(userService.selectSpelByKey("tenant1")).isEqualTo("tenant1");
assertThat(userService.selecSpelByTenant(new User("tenant2"))).isEqualTo("tenant2");
}
+
+ private DataSourceProperty createDataSourceProperty(String poolName) {
+ DataSourceProperty result = new DataSourceProperty();
+ result.setPoolName(poolName);
+ result.setDriverClassName("org.h2.Driver");
+ result.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:db/spring-expression-language.sql'");
+ result.setUsername("sa");
+ result.setPassword("");
+ return result;
+ }
}
@SpringBootApplication
diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java
index ca87dd6..cf4fe81 100644
--- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java
+++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/controller/UserController.java
@@ -18,7 +18,6 @@ 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;
@@ -29,8 +28,11 @@ import java.util.List;
@RestController
public class UserController {
- @Autowired
- private UserService userService;
+ private final UserService userService;
+
+ public UserController(UserService userService) {
+ this.userService = userService;
+ }
@GetMapping("/session")
public List session(HttpServletRequest request) {
diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java
index 3608bab..55c7ea0 100644
--- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java
+++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/SchoolService.java
@@ -20,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class SchoolService {
+
private final TeacherService teacherService;
private final StudentService studentService;
diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java
index 53c4815..6386a75 100644
--- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java
+++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/StudentService.java
@@ -32,6 +32,7 @@ import java.util.List;
@Service
@DS("student")
public class StudentService {
+
private final DataSource dataSource;
public StudentService(DataSource dataSource) {
diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java
index dda872f..bfdc1c4 100644
--- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java
+++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/service/nest/TeacherService.java
@@ -32,6 +32,7 @@ import java.util.List;
@Service
@DS("teacher")
public class TeacherService {
+
private final DataSource dataSource;
public TeacherService(DataSource dataSource) {
diff --git a/pom.xml b/pom.xml
index d588657..fa63d89 100644
--- a/pom.xml
+++ b/pom.xml
@@ -119,6 +119,16 @@
druid
${druid.version}
+
+ com.alibaba
+ druid-spring-boot-starter
+ ${druid.version}
+
+
+ com.alibaba
+ druid-spring-boot-3-starter
+ ${druid.version}
+
org.springframework.boot
spring-boot-starter-jta-atomikos
@@ -261,6 +271,24 @@
+
+ jdk11+
+
+ [11,)
+
+
+
+
+
+ maven-surefire-plugin
+
+ --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
+
+
+
+
+
+
release