1. 程式人生 > >spring boot整合mybatis通用mapper實現Druid多資料來源

spring boot整合mybatis通用mapper實現Druid多資料來源

      在以前的專案中用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 {
<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"dataSourceOne"</span>)
<span style="color:#bbb529;">@ConfigurationProperties</span>(<span style="color:#d0d0ff;">prefix </span>= <span style="color:#6a8759;">"spring.datasource.source1"</span>)
<span style="color:#bbb529;">@Primary </span><span style="color:#808080;">//設定主資料來源

public DataSource DataSourceOne(){ DruidDataSource dataSource = new DruidDataSource(); return dataSource; }

<span style="color:#bbb529;">@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; }

<span style="color:#bbb529;">@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; }

<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"sqlSessionFactoryOne"</span>)
<span style="color:#bbb529;">@Primary

public SqlSessionFactory sqlSessionFactoryOne(@Qualifier(“dataSourceOne”) DataSource dataSource)throws Exception{ SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean.getObject(); }

<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"dataSourceTransactionManagerOne"</span>)
<span style="color:#bbb529;">@Primary

public DataSourceTransactionManager dataSourceTransactionManagerOne(@Qualifier(“dataSourceOne”) DataSource dataSource){ return new DataSourceTransactionManager(dataSource); }

<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"sqlSessionTemplateOne"</span>)
<span style="color:#bbb529;">@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 {
<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"dataSourceTwo"</span>)
<span style="color:#bbb529;">@ConfigurationProperties</span>(<span style="color:#d0d0ff;">prefix </span>= <span style="color:#6a8759;">"spring.datasource.source2"</span>)
<span style="color:#cc7832;">public </span>DataSource <span style="color:#ffc66d;">DataSourceOne</span>(){
    DruidDataSource dataSource = <span style="color:#cc7832;">new </span>DruidDataSource()<span style="color:#cc7832;">;

return dataSource; }

<span style="color:#bbb529;">@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; }

<span style="color:#bbb529;">@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; }

<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"sqlSessionFactoryTwo"</span>)
<span style="color:#cc7832;">public </span>SqlSessionFactory <span style="color:#ffc66d;">sqlSessionFactoryOne</span>(<span style="color:#bbb529;">@Qualifier</span>(<span style="color:#6a8759;">"dataSourceTwo"</span>) DataSource dataSource)<span style="color:#cc7832;">throws </span>Exception{
    SqlSessionFactoryBean bean = <span style="color:#cc7832;">new </span>SqlSessionFactoryBean()<span style="color:#cc7832;">;

bean.setDataSource(dataSource); return bean.getObject(); }

<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"dataSourceTransactionManagerTwo"</span>)
<span style="color:#cc7832;">public </span>DataSourceTransactionManager <span style="color:#ffc66d;">dataSourceTransactionManagerOne</span>(<span style="color:#bbb529;">@Qualifier</span>(<span style="color:#6a8759;">"dataSourceTwo"</span>) DataSource dataSource){
    <span style="color:#cc7832;">return new </span>DataSourceTransactionManager(dataSource)<span style="color:#cc7832;">;

}

<span style="color:#bbb529;">@Bean</span>(<span style="color:#d0d0ff;">name </span>= <span style="color:#6a8759;">"sqlSessionTemplateTwo"</span>)
<span style="color:#cc7832;">public </span>SqlSessionTemplate <span style="color:#ffc66d;">sqlSessionTemplateOne</span>(<span style="color:#bbb529;">@Qualifier</span>(<span style="color:#6a8759;">"sqlSessionFactoryTwo"</span>) SqlSessionFactory sqlSessionFactory)<span style="color:#cc7832;">throws </span>Exception{
    <span style="color:#cc7832;">return new </span>SqlSessionTemplate(sqlSessionFactory)<span style="color:#cc7832;">;

}

到這裡,基本的資料來源配置就已經差不多結束了,接下來的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 {
<span style="color:#bbb529;">@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;
}
<span style="color:#bbb529;">@RequestMapping</span>(<span style="color:#6a8759;">"/getAllUserForOne"</span>)
<span style="color:#cc7832;">public </span>List&lt;UserInfoEntity&gt; <span style="color:#ffc66d;">getAllUserForOne</span>(){
    List&lt;UserInfoEntity&gt; allUser = <span style="color:#9876aa;">userInfoOneMapper</span>.selectAll()<span style="color:#cc7832;">;

return allUser; }

<span style="color:#bbb529;">@RequestMapping</span>(<span style="color:#6a8759;">"/getTwoUserById"</span>)
<span style="color:#cc7832;">public </span>UserInfoEntity <span style="color:#ffc66d;">getTwoUserById</span>(Integer id){
    UserInfoEntity entity = <span style="color:#cc7832;">new </span>UserInfoEntity()<span style="color:#cc7832;">;

entity.setId(id); UserInfoEntity entity1 = userInfoTwoMapper.selectOne(entity); return entity1; }

<span style="color:#bbb529;">@RequestMapping</span>(<span style="color:#6a8759;">"/getAllUserForTwo"</span>)
<span style="color:#cc7832;">public </span>List&lt;UserInfoEntity&gt; <span style="color:#ffc66d;">getAllUserForTwo</span>(){
    List&lt;UserInfoEntity&gt; allUser = <span style="color:#9876aa;">userInfoTwoMapper</span>.selectAll()<span style="color:#cc7832;">;

return allUser; } }

啟動專案,在postman裡面呼叫不同的介面,可以獲取到不同的表裡面的資料。                                                                       

呼叫getOneUserById,傳id=1獲得返回資料:

呼叫getTwoUserById,傳id=1獲得返回資料: