在以前的項目中用springMVC加原生的mybatis架構使用過多資料源的配置,是用xml配置的。在這次的新項目裡面使用到了tk的通用mapper,剛好項目結束,利用空閑時間寫了個全注解的多資料源配置小demo。
現在網際網路項目中流行使用Mybatis架構和Druid資料庫連接配接池進行資料庫的操作。本來直接是用的spring boot整合mybatis做的多資料源,因為剛結束的項目中使用到了通用mapper這個免去sql編寫,提高開發效率的元件,是以順帶的把這個元件也內建進來了。
因為主要講的是多資料源的實作,對其他的架構元件就不花費太多的筆墨,以後會另外的花時間去記錄。
首先看下項目的整體結構:
datasource包下面放的是資料源一和資料源二的配置
mapper包下面放的對應的mapper檔案,注意包要細分到不同的來源,比喻mapper.source1和mapper.source2,不同來源庫的mapper檔案要放到不同的source包下面。
項目是用maven工具建構的,肯定少不了在pom.xml檔案裡面添加相應的jar依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lms</groupId>
<artifactId>multiple-datasource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>multiple-datasource</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid連接配接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--tk通用mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加完依賴之後就要開始配置資料庫了,在application.properties檔案裡面配置資料庫的位址和druid相關的一些配置:
mybatis.type-aliases-package=com.lms.multipledatasource.entity
spring.datasource.source1.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.source1.url = jdbc:mysql://192.168.2.115:3306/data_source_test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.source1.username = root
spring.datasource.source1.password = 8Nj1jo+I8f1qNQ
#使用Druid資料源
spring.datasource.source1.initialSize=5
# 初始化大小,最小,最大
spring.datasource.source1.minIdle=5
spring.datasource.source1.maxActive= 20
# 配置擷取連接配接等待逾時的時間
spring.datasource.source1.maxWait= 60000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接配接,機關是毫秒
spring.datasource.source1.timeBetweenEvictionRunsMillis= 60000
# 配置一個連接配接在池中最小生存的時間,機關是毫秒
spring.datasource.source1.minEvictableIdleTimeMillis= 300000
spring.datasource.source1.validationQuery= select 'x'
spring.datasource.source1.testWhileIdle= true
spring.datasource.source1.testOnBorrow= false
spring.datasource.source1.testOnReturn= false
# 打開PSCache,并且指定每個連接配接上PSCache的大小
spring.datasource.source1.poolPreparedStatements= true
spring.datasource.source1.maxPoolPreparedStatementPerConnectionSize= 20
# 配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用于防火牆
spring.datasource.source1.filters= stat,wall,slf4j
# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
spring.datasource.source1.connectionProperties= druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.source2.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.source2.url = jdbc:mysql://192.168.2.115:3306/data_source_test2?useUnicode=true&characterEncoding=utf-8
spring.datasource.source2.username = root
spring.datasource.source2.password = 8Nj1jo+I8f1qNQ
#使用Druid資料源
spring.datasource.source2.initialSize=5
# 初始化大小,最小,最大
spring.datasource.source2.minIdle=5
spring.datasource.source2.maxActive= 20
# 配置擷取連接配接等待逾時的時間
spring.datasource.source2.maxWait= 60000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接配接,機關是毫秒
spring.datasource.source2.timeBetweenEvictionRunsMillis= 60000
# 配置一個連接配接在池中最小生存的時間,機關是毫秒
spring.datasource.source2.minEvictableIdleTimeMillis= 300000
spring.datasource.source2.validationQuery= select 'x'
spring.datasource.source2.testWhileIdle= true
spring.datasource.source2.testOnBorrow= false
spring.datasource.source2.testOnReturn= false
# 打開PSCache,并且指定每個連接配接上PSCache的大小
spring.datasource.source2.poolPreparedStatements= true
spring.datasource.source2.maxPoolPreparedStatementPerConnectionSize= 20
# 配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用于防火牆
spring.datasource.source2.filters= stat,wall,slf4j
# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
spring.datasource.source2.connectionProperties= druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
mybatis.type-aliases-package配置可以自動的掃描mapper檔案,但是需要在Mapper接口上标注@Mapper注解,下面配置了兩個資料源source1和source2,如果還有更多的資料源,隻需要依次的添加就可以了。
接下來建立兩個資料源配置類DataSourceOneConfig和DataSourceTwoConfig
在配置資料源的時候,必要要配置一個主資料源,在這裡把DataSourceOneConfig作為主資料源
@Configuration
//掃描Mapper basePackages要精确到source1目錄便于進行不同資料源的區分
@MapperScan(basePackages = "com.lms.multipledatasource.mapper.source1", sqlSessionTemplateRef = "sqlSessionTemplateOne")
public class DataSourceOneConfig {
@Bean(name = "dataSourceOne")
@ConfigurationProperties(prefix = "spring.datasource.source1")
@Primary //設定主資料源
public DataSource DataSourceOne(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
public ServletRegistrationBean druidStatViewServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
registrationBean.addInitParameter("allow", "127.0.0.1"); // IP白名單 (沒有配置或者為空,則允許所有通路)
registrationBean.addInitParameter("deny", ""); // IP黑名單 (存在共同時,deny優先于allow)
registrationBean.addInitParameter("loginUsername", "admin");
registrationBean.addInitParameter("loginPassword", "admin");
registrationBean.addInitParameter("resetEnable", "false");
return registrationBean;
}
@Bean
public FilterRegistrationBean druidWebStatViewFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new WebStatFilter());
registrationBean.addInitParameter("urlPatterns", "/*");
registrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
return registrationBean;
}
@Bean(name = "sqlSessionFactoryOne")
@Primary
public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceOne") DataSource dataSource)throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "dataSourceTransactionManagerOne")
@Primary
public DataSourceTransactionManager dataSourceTransactionManagerOne(@Qualifier("dataSourceOne") DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sqlSessionTemplateOne")
@Primary
public SqlSessionTemplate sqlSessionTemplateOne(@Qualifier("sqlSessionFactoryOne") SqlSessionFactory sqlSessionFactory)throws Exception{
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@Configuration 說明這是一個配置類
@MapperScan 掃描mapper接口和進行容器管理,注意的是basePackages要精确到source1目錄便于和不同資料源的區分
@Primary 标志主資料源,一定要有且隻能有一個主資料源,不然會報錯的。
@ConfigurationProperties 讀取properties配置檔案裡面的以spring.datasource.source1開頭的資料庫配置
在配置datasource的時候一定要用DruidDataSource類,不然的話druid資料庫連接配接池是不會起作用的
public DataSource DataSourceOne(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
druidStatViewServlet()和druidWebStatViewFilter()是配置durid的登陸位址和登陸賬戶的。
同理DataSourceTwoConfig類中的配置和DataSourceOneConfig裡面的是差不多的 ,把source1改為source2即可,并且不需要@Primary注解
@Configuration
@MapperScan(basePackages = "com.lms.multipledatasource.mapper.source2", sqlSessionTemplateRef = "sqlSessionTemplateTwo")
public class DataSourceTwoConfig {
@Bean(name = "dataSourceTwo")
@ConfigurationProperties(prefix = "spring.datasource.source2")
public DataSource DataSourceOne(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
public ServletRegistrationBean druidStatViewServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
registrationBean.addInitParameter("allow", "127.0.0.1"); // IP白名單 (沒有配置或者為空,則允許所有通路)
registrationBean.addInitParameter("deny", ""); // IP黑名單 (存在共同時,deny優先于allow)
registrationBean.addInitParameter("loginUsername", "admin");
registrationBean.addInitParameter("loginPassword", "admin");
registrationBean.addInitParameter("resetEnable", "false");
return registrationBean;
}
@Bean
public FilterRegistrationBean druidWebStatViewFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new WebStatFilter());
registrationBean.addInitParameter("urlPatterns", "/*");
registrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
return registrationBean;
}
@Bean(name = "sqlSessionFactoryTwo")
public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceTwo") DataSource dataSource)throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "dataSourceTransactionManagerTwo")
public DataSourceTransactionManager dataSourceTransactionManagerOne(@Qualifier("dataSourceTwo") DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sqlSessionTemplateTwo")
public SqlSessionTemplate sqlSessionTemplateOne(@Qualifier("sqlSessionFactoryTwo") SqlSessionFactory sqlSessionFactory)throws Exception{
return new SqlSessionTemplate(sqlSessionFactory);
}
到這裡,基本的資料源配置就已經差不多結束了,接下來的service,mapper,conttroller就和平常寫項目是一樣的,沒有什麼太大的差別。
因為使用的是tk通用mapper,是以我們在自己定義一個接口去是繼承tk的兩個接口Mapper<T>, MySqlMapper<T> ,自己定義的接口名稱可以随自己定,和普通的接口一樣,沒有特殊的要求。在這裡取名為CommnMapper<T>,注意的是一定要帶上泛型。這個接口上面不需要任何的注解
public interface CommnMapper<T> extends Mapper<T>, MySqlMapper<T> {
}
然後建立一個UserInfoOneMapper接口繼承剛剛建立的CommnMapper接口,接口上面要添加@Component和@Mapper來說明這個接口是一個元件和一個mapper檔案
@Component
@Mapper
public interface UserInfoOneMapper extends CommnMapper<UserInfoEntity>{
}
這個mapper連接配接的是userinfo表,是以泛型裡面用的是UserInfoEntity對象。mapper連接配接的是哪個表,泛型裡面對應的就是哪個表對應的實體類對象。
@Component
@Table(name = "userinfo")
public class UserInfoEntity {
@Id
private Integer id;
private String userName;
private String departName;
private Date created;
@Table裡面name的值是資料庫裡面對應的表名,一定不要填錯了。
然後我們就可以在service裡面調用mapper的增删查改方法來對表裡面的資料進行對應的操作了。因為這隻是一個demo,是以就沒有建立service層,直接在controller執行個體化了mapper調用了對應的方法
@RestController
public class UserInfoController {
@Autowired
private UserInfoOneMapper userInfoOneMapper;
@Autowired
private UserInfoTwoMapper userInfoTwoMapper;
@RequestMapping("/getOneUserById")
public UserInfoEntity getOneUserById(Integer id){
UserInfoEntity entity = new UserInfoEntity();
entity.setId(id);
UserInfoEntity entity1 = userInfoOneMapper.selectOne(entity);
return entity1;
}
@RequestMapping("/getAllUserForOne")
public List<UserInfoEntity> getAllUserForOne(){
List<UserInfoEntity> allUser = userInfoOneMapper.selectAll();
return allUser;
}
@RequestMapping("/getTwoUserById")
public UserInfoEntity getTwoUserById(Integer id){
UserInfoEntity entity = new UserInfoEntity();
entity.setId(id);
UserInfoEntity entity1 = userInfoTwoMapper.selectOne(entity);
return entity1;
}
@RequestMapping("/getAllUserForTwo")
public List<UserInfoEntity> getAllUserForTwo(){
List<UserInfoEntity> allUser = userInfoTwoMapper.selectAll();
return allUser;
}
}
啟動項目,在postman裡面調用不同的接口,可以擷取到不同的表裡面的資料。
調用getOneUserById,傳id=1獲得傳回資料:
調用getTwoUserById,傳id=1獲得傳回資料: