我的個人網站:
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命名空間要和接口對應