SpringBoot2.x整合mybatis多數據源

我的個人網站:
http://riun.xyz


當項目中要用到兩個不同的數據庫時,就需要配置兩個數據源分別連接這兩個庫。有的同學可能會問,將所有的表都放在一個庫下面不就行了,爲什麼要用兩個庫呢?
所有表都放在一個庫下當然可以,但是實際項目中,業務邏輯複雜之後,可能一些業務相關的庫在同一個表中,另一塊業務相關的數據就是在另一個庫裏,業務需求就是需要連接不同的數據庫,這你怎麼辦嘛。

示例:

數據庫信息

兩個數據庫:data和demo
在這裏插入圖片描述
這裏用data中的user表
在這裏插入圖片描述
和demo中的user表
在這裏插入圖片描述
做例子。

在項目中,由於兩個表名都叫user,爲了區分,demo中的user表對應javabean爲Demo.java,data中的user表對應javabean爲User.java

項目信息:

目錄:
在這裏插入圖片描述

依賴

pom.xml
這裏用的是SpringBoot2.2.2

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>hx.insist</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>多數據源</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--Swagger依賴-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--fastjson依賴-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.33</version>
        </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>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>

    </build>

</project>

配置文件

application.properties(properties和yml、yaml均可)
配置多個數據源連接,配置mapper.xml的掃描路徑
注意:
Spring1.0+配置多數據源是寫spring.datasource.url 和spring.datasource.driverClassName。
Spring2.0+配置多數據源是寫spring.datasource.jdbc-url和spring.datasource.driver-class-name。
名稱不一樣,如果還像1.0那樣寫會報jdbcUrl is required with driverClassName.錯誤!

server.port=9091

spring.datasource.one.jdbc-url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8
spring.datasource.one.username=root
spring.datasource.one.password=hanxu
spring.datasource.one.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.two.jdbc-url=jdbc:mysql://localhost:3306/data?useUnicode=true&characterEncoding=utf-8
spring.datasource.two.username=root
spring.datasource.two.password=hanxu
spring.datasource.two.driver-class-name=com.mysql.cj.jdbc.Driver


# mapper掃描
mybatis.mapper-locations=classpath:static/mybatis/mapper/*/*.xml
# 下劃線轉駝峯
mybatis.configuration.map-underscore-to-camel-case=true

多數據源配置信息

數據源1配置類:

package hx.insist.demo.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.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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
/*
 *  @Configuration :// 註冊到springBoot容器中
 *  @MapperScan(basePackages = "com.dengwei.springdemo.test1", sqlSessionFactoryRef = "sqlSessionFactory1")
 *  當前掃描包:com.dengwei.springdemo.test1下使用此數據源;sqlSessionFactoryRef:對應下面的sql會話工廠
 *  @Bean(name = "DataSource1")  :給當前注入的bean對象取的名字
 *  @ConfigurationProperties(prefix = "spring.datasource.hikari.test1")   application.properteis中對應屬性的前綴
 *  @Primary  : 設置默認數據源,當多個數據源時,不加會報錯
 */
@Configuration
@MapperScan(basePackages = "hx.insist.demo.mapper.meituan", sqlSessionFactoryRef = "sqlSessionFactory1")
public class DataSource1Config {

    /**
     *
     * @methodDesc: 功能描述:(配置test1數據庫)
     */
    @Bean(name = "DataSource1")
    @ConfigurationProperties(prefix = "spring.datasource.one")
    @Primary
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     *
     * @methodDesc: 功能描述:(test1 sql會話工廠)
     * @returnType:@param dataSource
     * @returnType:@throws Exception SqlSessionFactory

     */
    @Bean(name = "sqlSessionFactory1")
    @Primary
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("DataSource1") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //mybatis寫配置文件(sql映射)需要加下面的代碼
         bean.setMapperLocations(
                 new PathMatchingResourcePatternResolver().getResources("classpath:static/mybatis/mapper/DS1/*.xml"));
        return bean.getObject();
    }

    /**
     *
     * @methodDesc: 功能描述:(test1 事物管理)
     */
    @Bean(name = "test1TransactionManager")
    @Primary
    public DataSourceTransactionManager testTransactionManager(@Qualifier("DataSource1") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "test1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

數據源2配置類:

package hx.insist.demo.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.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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/*
 *  @Configuration :// 註冊到springBoot容器中
 *  @MapperScan(basePackages = "com.dengwei.springdemo.test2", sqlSessionFactoryRef = "SqlSessionFactory2")
 *  當前掃描包:com.dengwei.springdemo.test2 下使用此數據源;sqlSessionFactoryRef:對應下面的sql回話工廠
 *  @Bean(name = "DataSource2")  :給當前注入的bean對象取的名字
 *  @ConfigurationProperties(prefix = "spring.datasource.hikari.test2")   application.properteis中對應屬性的前綴
 *
 */
@Configuration
@MapperScan(basePackages = "hx.insist.demo.mapper.hbxj", sqlSessionFactoryRef = "sqlSessionFactory2")
public class DataSource2Config {

    /**
     *
     * @methodDesc: 功能描述:(配置test2數據庫)
     */
    @Bean(name = "DataSource2")
    @ConfigurationProperties(prefix = "spring.datasource.two")
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     *
     * @methodDesc: 功能描述:(test2 sql會話工廠)
     * @returnType:@param dataSource
     * @returnType:@throws Exception SqlSessionFactory

     */
    @Bean(name = "sqlSessionFactory2")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("DataSource2") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //mybatis寫配置文件(sql映射)需要加下面的代碼
         bean.setMapperLocations(
                 new PathMatchingResourcePatternResolver().getResources("classpath:static/mybatis/mapper/DS2/*.xml"));
        return bean.getObject();
    }

    /**
     *
     * @methodDesc: 功能描述:(test2 事物管理)
     */
    @Bean(name = "test2TransactionManager")
    public DataSourceTransactionManager testTransactionManager(@Qualifier("DataSource2") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "test2SqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

配置好數據源信息後,就可以寫po、mapper、service、controller來測試了:

PO

Demo類:

package hx.insist.demo.domain.meituan.Po;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Demo {
    private Long id;
    private String emp;
    private String name;
    private String address;
    private String tel;
    private Integer salary;
    //將時間戳數字自動轉換爲對應時間格式
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

Usre類:

package hx.insist.demo.domain.hbxj.Po;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author: HanXu
 * on 2019/12/19
 * Class description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

mapper

DemoMapper類:

package hx.insist.demo.mapper.meituan;

import hx.insist.demo.domain.meituan.Po.Demo;

import java.util.List;

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */

public interface DemoMapper {
    List<Demo> getAll();
}

對應的xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="hx.insist.demo.mapper.meituan.DemoMapper">
    <resultMap id="BaseResultMap" type="hx.insist.demo.domain.meituan.Po.Demo">
        <id column="id" jdbcType="BIGINT" property="id" />
        <result column="emp" jdbcType="VARCHAR" property="emp" />
        <result column="name" jdbcType="VARCHAR" property="name" />
        <result column="address" jdbcType="VARCHAR" property="address" />
        <result column="tel" jdbcType="VARCHAR" property="tel" />
        <result column="salary" jdbcType="INTEGER" property="salary" />
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
    </resultMap>
    <select id="getAll" resultMap="BaseResultMap">
        select * from user
    </select>
</mapper>

UserMapper類:

package hx.insist.demo.mapper.hbxj;

import hx.insist.demo.domain.hbxj.Po.User;

import java.util.List;

/**
 * @author: HanXu
 * on 2019/12/19
 * Class description:
 */
public interface UserMapper {
    List<User>  getAll();
}

對應的xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="hx.insist.demo.mapper.hbxj.UserMapper">
    <resultMap id="BaseResultMap" type="hx.insist.demo.domain.hbxj.Po.User">
        <id column="id" jdbcType="INTEGER" property="id" />
        <result column="name" jdbcType="VARCHAR" property="name" />
        <result column="age" jdbcType="INTEGER" property="age" />
    </resultMap>
    <select id="getAll" resultMap="BaseResultMap">
        select * from user
    </select>
</mapper>

xml中mapper標籤的namespace一定要和對應的mapper接口路徑一致

service

DemoService.java:

package hx.insist.demo.service.meituan;

import hx.insist.demo.domain.meituan.Po.Demo;
import hx.insist.demo.mapper.meituan.DemoMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */
@Service
public class DemoService {
    @Resource
    private DemoMapper demoMapper;

    public List<Demo> getAll(){
        return demoMapper.getAll();
    }
}

UserService.java:

package hx.insist.demo.service.hbxj;

import hx.insist.demo.domain.hbxj.Po.User;
import hx.insist.demo.mapper.hbxj.UserMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author: HanXu
 * on 2019/12/19
 * Class description:
 */
@Service
public class UserService {
    @Resource
    private UserMapper userMapper;

    public List<User> getAll(){
        return userMapper.getAll();
    }
}

controller

package hx.insist.demo.ui;

import hx.insist.demo.service.hbxj.UserService;
import hx.insist.demo.service.meituan.DemoService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author: HanXu
 * on 2019/12/18
 * Class description:
 */
@Api("用戶操作")
@RestController
public class UserController {

    @Autowired
    private DemoService demoService;
    @Autowired
    private UserService userService;


    @GetMapping("meituanDemos")
    public ResponseEntity getAllDs1(){
        return ResponseEntity.ok(demoService.getAll());
    }

    @GetMapping("hbxjUsers")
    public ResponseEntity getAllDs2(){
        return ResponseEntity.ok(userService.getAll());
    }
}

啓動類

啓動類要配置mapper接口掃描

package hx.insist.demo;

import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.math.BigInteger;

@EnableSwagger2
//@MapperScan({"hx.insist.demo.mapper.hbxj","hx.insist.demo.mapper.meituan"})
@MapperScan("hx.insist.demo.mapper")//這兩個掃描路徑都可以
@SpringBootApplication
public class DemoApplication {

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


    /**
     * 使用@Bean註解注入第三方的解析框架(fastJson)
     */
    @Bean
    public HttpMessageConverters fastHttpMessageConverters() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

        //配置
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        //解決Long精度丟失問題
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);

        //配置setter
        converter.setFastJsonConfig(fastJsonConfig);
        HttpMessageConverter<?> converter2 = converter;
        return new HttpMessageConverters(converter2);
    }
}

測試

瀏覽器輸入http://localhost:9091/swagger-ui.html進入swagger測試:
在這裏插入圖片描述
執行成功:
在這裏插入圖片描述
在這裏插入圖片描述

總結:

配置多數據源注意事項:

  • 配置文件中多數據源用不同詞綴分辨:spring.datasource.one、spring.datasource.two
  • 配置文件中要配置mapper.xml掃描路徑:mybatis.mapper-locations=classpath:static/mybatis/mapper//.xml
  • SpringBoot2.0寫法有所改變:spring.datasource.one.jdbc-url、spring.datasource.one.driver-class-name
  • 多數據源配置類上要配置對應的mapper接口掃描路徑、mapper.xml掃描路徑和配置文件對應配置前綴
  • 啓動類要加mapper接口掃描
  • mapper.xml文件中的mapper標籤的namespace命名空間要和接口對應
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章