SpringBoot+MyBatis配置多數據源


SpringBoot 可以支持多數據源,這是一個非常值得學習的功能,但是從現在主流的微服務的架構模式中,每個應用都具有唯一且准確的功能,多數據源的需求很難用到,考慮到實際情況遠遠比理論復雜的多,這里還是深入學習一個Mybatis的多數據源的配置,代碼偏向於實戰,提供Git地址,以供下載測試.https://gitee.com/zhoutao825638/Sprinboot_mybatis_ds.git

數據庫腳本

我們首先聲明記錄一下數據庫腳本創建了兩個數據庫,test1和test2 ,並且分別在不同的數據庫中創建了student和lesson表.

CREATE DATABASE `test1` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;  ;
USE `test1`;
CREATE TABLE `student`(
  `id` VARCHAR(12) PRIMARY KEY,
  `name` VARCHAR(36) NOT NULL ,
  `age` INTEGER  DEFAULT 0
);

-- 插入數據
INSERT INTO test1.student (id, name, age) VALUES ('1', '張夢為', 1);
INSERT INTO test1.student (id, name, age) VALUES ('2', '上官婉兒', 2);
INSERT INTO test1.student (id, name, age) VALUES ('3', '唐因', 2);


CREATE DATABASE `test2` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;  ;
USE `test2`;
CREATE TABLE `lesson`(
  `id` VARCHAR(12) PRIMARY KEY,
  `name` VARCHAR(36) NOT NULL ,
  `credit` FLOAT  DEFAULT 0,
  `teacher` VARCHAR(36) DEFAULT 0
);
-- 插入數據
INSERT INTO test2.lesson (id, name, credit, teacher) VALUES ('1', '大學物理', 5, '張思瑞');
INSERT INTO test2.lesson (id, name, credit, teacher) VALUES ('2', '高等數學', 5, '李佛');

創建Spring 應用

使用IDEA 可以非常簡單的創建一個應用,這里我使用了Gradle構建項目,其依賴如下:

lombok 是一個不錯的插件,推薦使用,如果不使用lombok的話,下面的代碼需要添加set/get方法

    compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2')
    compile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '1.3.2'
    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.47'
    compileOnly('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    compile('org.springframework.boot:spring-boot-starter-web')

配置完成之后,在應用的入口中,我們需要修改一下

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

這是因為SpringBoot會自動根據依賴來自動配置,但是我們的數據源配置被我們自己自定義配置了,此時SpringBoot 無法完成自動化配置,因此就會報錯,所以此處我們需要排除DataSourceAutoConfiguration的自動配置.

配置數據源

這里我們配置來兩個數據源 一個是test1,一個test2,修改application.properties文件


-- 數據源 Frist
spring.datasource.first.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.first.username=root
spring.datasource.first.password=
spring.datasource.first.driverClassName=com.mysql.jdbc.Driver

-- 數據源 Second
spring.datasource.second.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8
spring.datasource.second.username=root
spring.datasource.second.password=
spring.datasource.second.driverClassName=com.mysql.jdbc.Driver

創建配置文件封裝類

為了更合理的使用配置文件,這里我們沒有使用之前的@Value,而是自己封裝一個PropertiesConfig類對象.如下

@Data注解需要添加Lombok插件並開啟,需要不想安裝的話,請為下面的四個成員變量提供set/get方法即可

數據源First配置文件封裝

package com.zhoutao123.springboot.muldatasources.config;


import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.first")
public class FirstDataBaseProperties {
  String url;
  String username;
  String password;
  String driverClassName;
}

數據源Second配置文件封裝

package com.zhoutao123.springboot.muldatasources.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.second")
public class SecondDataBaseProperties {
  String url;
  String username;
  String password;
  String driverClassName;
}

完成數據源配置

這里需要完成DataSource/SqlSessionFactory/SessionTemp等對象的注入,需要注意的是,不管配置多少個數據源,其中的一個數據源配置的Bean必須使用@Primary完成注解.

下面是兩個數據源的配置,其中First使用了@Primary注解

MapperScan注解的basePackages 表示了其目錄下的Mapper使用文件使用該數據源,如FirstDataSource中表示com.zhoutao123.springboot.muldatasources.mapper.first下的Maper文件將使用FirstDataSource.

package com.zhoutao123.springboot.muldatasources.config;

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.Autowired;
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
@MapperScan(basePackages = "com.zhoutao123.springboot.muldatasources.mapper.first",sqlSessionTemplateRef ="firstSqlSessionTemplate")
public class FirstDataSourceConfig {

  @Autowired
  private FirstDataBaseProperties prop;

  //    創建數據源
  @Bean(name = "firstDS")
  @ConfigurationProperties(prefix = "spring.datasource.first")
  @Primary
  public DataSource getFirstDataSource() {
    DataSource build =  DataSourceBuilder.create()
            .driverClassName(prop.driverClassName)
            .url(prop.url)
            .username(prop.username)
            .password(prop.password)
            .build();
    return build;
    }


  // 創建SessionFactory
  @Bean(name = "firstSqlSessionFactory")
  @Primary
  public SqlSessionFactory firstSqlSessionFactory(@Qualifier("firstDS") DataSource dataSource) throws Exception {
    SqlSessionFactoryBean  bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    return bean.getObject();
  }

  // 創建事務管理器

  @Bean("firstTransactionManger")
  @Primary
  public DataSourceTransactionManager firstTransactionManger(@Qualifier("firstDS") DataSource dataSource){
    return new DataSourceTransactionManager(dataSource);
  }

  // 創建SqlSessionTemplate

  @Bean(name = "firstSqlSessionTemplate")
  @Primary
  public SqlSessionTemplate firstSqlSessionTemplate(@Qualifier("firstSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
    return new SqlSessionTemplate(sqlSessionFactory);
  }


  private Class getType(String type) {
    try {
      return Class.forName(type);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }


}

以及第二個數據源的配置

package com.zhoutao123.springboot.muldatasources.config;

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.Autowired;
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.zhoutao123.springboot.muldatasources.mapper.second",sqlSessionTemplateRef ="secondSqlSessionTemplate")
public class SecondDataSourceConfig {

  @Autowired
  private SecondDataBaseProperties prop;

//    創建數據源
  @Bean(name = "secondDS")
  @ConfigurationProperties(prefix = "spring.datasource.second")
  public DataSource getSecondDataSource() {
    DataSource build =  DataSourceBuilder.create()
            .driverClassName(prop.driverClassName)
            .url(prop.url)
            .username(prop.username)
            .password(prop.password)
            .build();
    return build;
  }


  // 創建SessionFactory
  @Bean(name = "secondSqlSessionFactory")
  public SqlSessionFactory secondSqlSessionFactory(@Qualifier("secondDS") DataSource dataSource) throws Exception {
    SqlSessionFactoryBean  bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    return bean.getObject();
  }

  // 創建事務管理器

  @Bean("secondTransactionManger")
  public DataSourceTransactionManager secondTransactionManger(@Qualifier("secondDS") DataSource dataSource){
    return new DataSourceTransactionManager(dataSource);
  }

  // 創建SqlSessionTemplate

  @Bean(name = "secondSqlSessionTemplate")
  public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
    return new SqlSessionTemplate(sqlSessionFactory);
  }

  private Class getType(String type) {
    try {
      return Class.forName(type);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }
}

實現Mapper

根據數據源配置的MappScan目錄來創建測試Mapper,代碼如下,注意包名,放在正確的位置上.

返回模型

這里寫了兩個數據庫映射模型,用於接受數據庫數據,比較簡單.

package com.zhoutao123.springboot.muldatasources.dao;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class Lesson {

    private String id;

    private String name;

    private String teacher;

    private  float credit;
}

package com.zhoutao123.springboot.muldatasources.dao;


import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class Student {

    private String id;

    private  String name;

    private String age;
}

創建映射Mapper

package com.zhoutao123.springboot.muldatasources.mapper.first;

import com.zhoutao123.springboot.muldatasources.dao.Student;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;


@Mapper
public interface StudentMapper {

	// 查詢全部的學生
    @Select("SELECT * FROM student;")
    List<Student> getAllStudent();

}

package com.zhoutao123.springboot.muldatasources.mapper.second;

import com.zhoutao123.springboot.muldatasources.dao.Lesson;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;


@Mapper
public interface LessonMapper {

	//	 查詢全部的課程
    @Select("SELECT * FROM lesson;")
    List<Lesson> getAllLesson();

}

測試接口

這里為了方便,寫了一個測試接口和Application放在一起的,同時考慮到這邊學習的主要目標是多數據源的配置,就沒有Service層,Controller直接調用Mapper,真實項目不要這么寫哈.

package com.zhoutao123.springboot.muldatasources;

import com.zhoutao123.springboot.muldatasources.config.FirstDataSourceConfig;
import com.zhoutao123.springboot.muldatasources.config.SecondDataSourceConfig;
import com.zhoutao123.springboot.muldatasources.dao.Lesson;
import com.zhoutao123.springboot.muldatasources.dao.Student;
import com.zhoutao123.springboot.muldatasources.mapper.first.StudentMapper;
import com.zhoutao123.springboot.muldatasources.mapper.second.LessonMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.PublicKey;
import java.util.List;

// 排除數據源的自動配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@RestController
public class MuldatasourcesApplication {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private LessonMapper lessonMapper;

    public static void main(String[] args) {
        SpringApplication.run(MuldatasourcesApplication.class, args);
    }


    @GetMapping("/student")
    public List<Student> studentList(){
        return studentMapper.getAllStudent();
    }

    @GetMapping("/lesson")
    public List<Lesson> lessonList(){
        return lessonMapper.getAllLesson();
    }
}

測試結果

可以看到不同的數據庫的數據被查詢出來了,實現了多數據源的切換,此處的效果和數據庫的讀寫分離有類似的效果,可以參考分析,學習.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM