SpringBoot + Mybatis + Druid configure multiple data sources
preface
With the increasing amount of concurrent data, a single database can not bear such a large pressure, so it is more and more important for a project to use multiple databases, of course, the use of database mode may be different, such as master-slave mode, distributed mode. Either pattern requires reading and writing to multiple databases, so you need to configure multiple data sources in your project. In the development of Java projects, the most commonly used data operation framework is Mybatis, and Spring Boot is basically used in the development framework. Spring Boot integrates Mybatis to realize multiple data sources in two ways: subcontracting and AOP. Subcontracting is used here because the hierarchy is clearer.
1. Prepare the database environment
Take Mysql as an example, create two local databases for testing. Create a new table user in the data_one library and a new table TEL in the data_two library. In this solution, there is no limit on the number of databases and different databases can be deployed on different servers.
The library structure is as follows:
The table structure is as follows:
2. Environment preparation
2.1 Environment Configuration
tool | version |
---|---|
Mysql | 8.0.16 |
SpringBoot | 2.2.7 |
Mybatis | 2.1.0 |
JDK | 1.8 |
2.2 Creating a SpringBoot project
2.2.1 Configuring POM Files and adding dependencies
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<optional>true</optional>
</dependency>
</dependencies>
Copy the code
2.2.2 Configuring the application.yml file
Add user and TEL in the outer layer of the original database configuration to distinguish databases. The configuration name can be selected by yourself, but do not use the same name.
Note: We used url for single-source configuration, but jDBC-URL for multi-source configuration
spring:
application:
name: datasource
datasource:
druid:
# Maximum active number
maxActive: 20
# initialize the number
initialSize: 1
# Maximum connection wait timeout
maxWait: 60000
validation-query: select 1;
filter: stat,wall
user: Configure the data_one database
jdbc-url: JDBC: mysql: / / 127.0.0.1:3306 / data_one? useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
tel: Configure the datA_two database
jdbc-url: JDBC: mysql: / / 127.0.0.1:3306 / data_two? useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
type-aliases-package: com.mulits.datasource.model Use hump annotation mapping
Copy the code
2.2.3 Modifying the startup Class
Because the project uses the Spring Boot framework, which will automatically configure the data source and automatically read the data source information from YML, when we configure the customized data source, Need to exclude = DataSourceAutoConfiguration banned from class for automatic configuration of data sources.
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DatasourceApplication {
public static void main(String[] args) { SpringApplication.run(DatasourceApplication.class, args); }}Copy the code
3. Case realization
3.1 Creating a Model DirectoryUser
,Tel
Entity class.
@Data
public class User implements Serializable {
private Long id;
private String name;
public User(Long id,String name){
this.id = id;
this.name = name; }}Copy the code
@Data
public class Tel implements Serializable {
private Long id;
private String tel;
public Tel(Long id,String tel){
this.id = id;
this.tel = tel; }}Copy the code
3.2 Creating the Config directory and creating the DataConfig class
3.2.1 Creating the UserDataConfig class
I set data_one as the Primary database, so I need to configure the @primary annotation.
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration // Register to the container
@MapperScan(basePackages = "com.mulits.datasource.mapper.user.**",
sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.user")// Set the configuration
public DataSource userDataSource(a) {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean
@Primary
public DataSourceTransactionManager userTransactionManager(@Qualifier("userDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@Primary
public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return newSqlSessionTemplate(sqlSessionFactory); }}Copy the code
3.2.2 Creating the TelDataConfig class
Since data_ONE is already set as the database, you do not need to add the @primary annotation when configuring the data_two database; otherwise, an error will be reported.
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.mulits.datasource.mapper.tel.**",
sqlSessionTemplateRef = "telSqlSessionTemplate")
public class TelDataConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.tel")
public DataSource telDataSource(a) {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory telSqlSessionFactory(@Qualifier("telDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean
public DataSourceTransactionManager telTransactionManager(@Qualifier("telDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SqlSessionTemplate telSqlSessionTemplate(@Qualifier("telSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return newSqlSessionTemplate(sqlSessionFactory); }}Copy the code
Note:
- When configuring multiple data sources, you must have a primary data source.
@Primary
Indicates that this Bean is considered first when there are more than one similar Bean candidate. When configuring multiple data sources, note that there must be a primary data source, using@Primary
Mark the Bean;@MapperScan
Mapper interface scanning and container management;
3.3 Creating a Mapper Directory
Mapper files of different databases cannot be contained in the same package. Config throws an injection error during injection. When used, the value is the same as when using a single data source.
3.3.1 Create a user directory in the mapper directory and create a UserMapper interface
@Mapper
@Repository
public interface UserMapper {
@Select("select * from user where id = #{id}")
List<User> selectUser(@Param("id") Long id);
}
Copy the code
3.3.2 In the Mapper directory, create a TEL directory and create a TelMapper interface
@Mapper
@Repository
public interface TelMapper {
@Select("select * from tel where id = #{id}")
List<Tel> selectTel(@Param("id") Long id);
}
Copy the code
4. Test configuration cases
4.1 Creating a Controller Class
Because this case mainly realizes multi-data source configuration, so I do not write the business class Service interface, directly inject Mapper;
@RestController
public class DataSourceController {
@Autowired
private UserMapper userMapper;
@Autowired
private TelMapper telMapper;
@GetMapping("/selectInfo/{id}")
public Map<String,Object> testSelect(@PathVariable("id") Long id){
Map<String,Object> map = new HashMap<>();
List<User> userInfo = userMapper.selectUser(id);
List<Tel> telInfo = telMapper.selectTel(id);
map.put("user",userInfo);
map.put("tel",telInfo);
returnmap; }}Copy the code
4.2 Querying Two Librariesid=1
Data and return
Open the browser, enter the address: http://localhost:8080/selectInfo/1
Springboot + Druid + MyBatis = Springboot + druid + MyBatis