首页 > 其他分享 >Spring Boot 整合多数据源

Spring Boot 整合多数据源

时间:2022-10-09 20:38:11浏览次数:47  
标签:Spring spring Boot Bean datasource 数据源 org DataSource


一、jdbcTemplate多数据源

1、依赖引入

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.28</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>

注意:这里的druid使用的是alibaba的druid-spring-boot-starter,而不是传统的druid,传统的druid没有datasource实例,需要我们自己配置,不推荐。因为 ​​druid-spring-boot-starter​​ 依赖提供了 DruidDataSourceBuilder 类,这个可以用来构建一个 DataSource 实例

2、数据源配置

spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=utf-8
spring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

这里通过 one 和 two 对数据源进行了区分,但是加了 one 和 two 之后,这里的配置就没法被 SpringBoot 自动加载了(因为前面的 key 变了),需要我们自己去加载 DataSource 了,此时,需要自己配置一个 DataSourceConfig,用来提供两个 DataSource Bean,如下:
 

@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}

这里提供了两个 Bean,其中 @ConfigurationProperties 是 Spring Boot 提供的类型安全的属性绑定,以第一个Bean为例, @ConfigurationProperties(prefix = "spring.datasource.one") 表示使用 spring.datasource.one 前缀的数据库配置去创建一个 DataSource,这样配置之后,我们就有了两个不同的 DataSource,接下来再用这两个不同的 DataSource 去创建两个不同的 JdbcTemplate。

3、配置 JdbcTemplate 实例

创建 JdbcTemplateConfig 类,用来提供两个不同的 JdbcTemplate 实例,如下

@Configuration
public class JdbcTemplateConfig {
@Bean
JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne") DataSource dsOne) {
return new JdbcTemplate(dsOne);
}
@Bean
JdbcTemplate jdbcTemplateTwo(@Qualifier("dsTwo") DataSource dsTwo) {
return new JdbcTemplate(dsTwo);
}
}

每一个 JdbcTemplate 的创建都需要一个 DataSource,由于 Spring 容器中现在存在两个 DataSource,默认使用类型查找,会报错,因此加上 @Qualifier 注解,表示按照名称查找。这里创建了两个 JdbcTemplate 实例,分别对应了两个 DataSource。接下来直接去使用这个 JdbcTemplate 就可以了。

4、测试

@RestController
public class HelloController {
@Autowired
@Qualifier("jdbcTemplateOne")
JdbcTemplate jdbcTemplateOne;
@Resource(name = "jdbcTemplateTwo")
JdbcTemplate jdbcTemplateTwo;

@GetMapping("/user")
public List<User> getAllUser() {
List<User> list = jdbcTemplateOne.query("select * from t_user", new BeanPropertyRowMapper<>(User.class));
return list;
}
@GetMapping("/user2")
public List<User> getAllUser2() {
List<User> list = jdbcTemplateTwo.query("select * from t_user", new BeanPropertyRowMapper<>(User.class));
return list;
}
}

和 DataSource 一样,Spring 容器中的 JdbcTemplate 也是有两个,因此不能通过 byType 的方式注入进来,这里给大伙提供了两种注入思路,

一种是使用 @Resource 注解,直接通过 byName 的方式注入进来

另外一种就是 @Autowired 注解加上 @Qualifier 注解,两者联合起来,实际上也是 byName。将 JdbcTemplate 注入进来之后,jdbcTemplateOne 和 jdbcTemplateTwo 此时就代表操作不同的数据源,使用不同的 JdbcTemplate 操作不同的数据源,实现了多数据源配置。

二、mybatis中使用多数据源

1、依赖

<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>2.0.0</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>
<version>5.1.28</version>
<scope>runtime</scope>
</dependency>

注意:这里的druid使用的是alibaba的druid-spring-boot-starter,而不是传统的druid,传统的druid没有datasource实例,需要我们自己配置,不推荐。因为 druid-spring-boot-starter 依赖提供了 DruidDataSourceBuilder 类,这个可以用来构建一个 DataSource 实例

2、配置

spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=utf-8
spring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

然后再提供两个 DataSource,如下:

@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}

3、MyBatis 配置

接下来则是 MyBatis 的配置,不同于 JdbcTemplate,MyBatis 的配置要稍微麻烦一些,因为要提供两个 Bean,因此这里两个数据源我将在两个类中分开来配置,首先来看第一个数据源的配置

@Configuration
@MapperScan(basePackages = "org.javayihao.mybatis.mapper1",sqlSessionFactoryRef = "sqlSessionFactory1",sqlSessionTemplateRef = "sqlSessionTemplate1")
public class MyBatisConfigOne {
@Resource(name = "dsOne")
DataSource dsOne;

@Bean
SqlSessionFactory sqlSessionFactory1() {
SqlSessionFactory sessionFactory = null;
try {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dsOne);
sessionFactory = bean.getObject();
} catch (Exception e) {
e.printStackTrace();
}
return sessionFactory;
}
@Bean
SqlSessionTemplate sqlSessionTemplate1() {
return new SqlSessionTemplate(sqlSessionFactory1());
}
}

创建 MyBatisConfigOne 类,首先指明该类是一个配置类,配置类中要扫描的包是 org.javayihao.mybatis.mapper1 ,即该包下的 Mapper 接口将操作 dsOne 中的数据,对应的 SqlSessionFactory 和 SqlSessionTemplate 分别是 sqlSessionFactory1 和 sqlSessionTemplate1,在 MyBatisConfigOne 内部,分别提供 SqlSessionFactory 和 SqlSessionTemplate 即可, SqlSessionFactory 根据 dsOne 创建,然后再根据创建好的SqlSessionFactory 创建一个 SqlSessionTemplate。

这里配置完成后,依据这个配置,再来配置第二个数据源即可:

@Configuration
@MapperScan(basePackages = "org.javayihao.mybatis.mapper2",sqlSessionFactoryRef = "sqlSessionFactory2",sqlSessionTemplateRef = "sqlSessionTemplate2")
public class MyBatisConfigTwo {
@Resource(name = "dsTwo")
DataSource dsTwo;

@Bean
SqlSessionFactory sqlSessionFactory2() {
SqlSessionFactory sessionFactory = null;
try {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dsTwo);
sessionFactory = bean.getObject();
} catch (Exception e) {
e.printStackTrace();
}
return sessionFactory;
}
@Bean
SqlSessionTemplate sqlSessionTemplate2() {
return new SqlSessionTemplate(sqlSessionFactory2());
}
}

这样 MyBatis 多数据源基本上就配置好了,接下来只需要在 org.javayihao.mybatis.mapper1 和 org.javayihao.mybatis.mapper2 包中提供不同的 Mapper,Service 中注入不同的 Mapper 就可以操作不同的数据源。
mapper 创建

org.javayihao.mybatis.mapper1 中的 mapper:

public interface UserMapperOne {
List<User> getAllUser();
}

对应的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="org.javayihao.mybatis.mapper1.UserMapperOne">
<select id="getAllUser" resultType="org.javayihao.mybatis.model.User">
select * from t_user;
</select>
</mapper>

org.javayihao.mybatis.mapper2 中的 mapper:

public interface UserMapper {
List<User> getAllUser();
}

对应的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="org.javayihao.mybatis.mapper2.UserMapper">
<select id="getAllUser" resultType="org.javayihao.mybatis.model.User">
select * from t_user;
</select>
</mapper>

之后我们在 Service 中注入两个不同的 Mapper,不同的 Mapper 将操作不同的数据源即可

三、jpa使用多数据源

1、依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
<version>5.1.28</version>
<scope>runtime</scope>
</dependency>

2、配置

#  数据源一
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=UTF-8
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource

# 数据源二
spring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=UTF-8
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

# Jpa配置
spring.jpa.properties.database=mysql
spring.jpa.properties.show-sql=true
spring.jpa.properties.database-platform=mysql
spring.jpa.properties.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

配置两个 DataSource

@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
@Primary
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}

这里的配置和前文的多数据源配置基本一致,但是注意多了一个在 Spring 中使用较少的注解 @Primary,这个注解一定不能少,否则在项目启动时会出错,@Primary 表示当某一个类存在多个实例时,优先使用哪个实例。

3、Jpa配置

我们将jpa两个数据源的配置分成两个类,第一个如下

@Configuration
@EnableJpaRepositories(basePackages = "org.javayihao.jpa.dao",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOne",transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfigOne {
@Autowired
@Qualifier(value = "dsOne")
DataSource dsOne;
@Autowired
JpaProperties jpaProperties;
@Bean
@Primary
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dsOne)
.packages("org.javayihao.jpa.model")
.properties(jpaProperties.getProperties())
.persistenceUnit("pu1")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryBeanOne = localContainerEntityManagerFactoryBeanOne(builder);
return new JpaTransactionManager(factoryBeanOne.getObject());
}
}

首先这里注入 dsOne,再注入 JpaProperties,JpaProperties 是系统提供的一个实例,里边的数据就是我们在 application.properties 中配置的 jpa 相关的配置。然后我们提供两个 Bean,分别是 LocalContainerEntityManagerFactoryBean 和 PlatformTransactionManager 事务管理器,不同于 MyBatis 和 JdbcTemplate,在 Jpa 中,事务一定要配置。在提供 LocalContainerEntityManagerFactoryBean 的时候,需要指定 packages,这里的 packages 指定的包就是这个数据源对应的实体类所在的位置,另外在这里配置类上通过 @EnableJpaRepositories 注解指定 dao 所在的位置,以及 LocalContainerEntityManagerFactoryBean 和 PlatformTransactionManager 分别对应的引用的名字。

好了,这样第一个就配置好了,第二个基本和这个类似,主要有几个不同点:

    dao 的位置不同
    persistenceUnit 不同
    相关 bean 的名称不同

注意实体类可以共用。

@Configuration
@EnableJpaRepositories(basePackages = "org.javayihao.jpa.dao2",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanTwo",transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfigTwo {
@Autowired
@Qualifier(value = "dsTwo")
DataSource dsTwo;
@Autowired
JpaProperties jpaProperties;
@Bean
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dsTwo)
.packages("org.javayihao.jpa.model")
.properties(jpaProperties.getProperties())
.persistenceUnit("pu2")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryBeanTwo = localContainerEntityManagerFactoryBeanTwo(builder);
return new JpaTransactionManager(factoryBeanTwo.getObject());
}
}

4、dao接口

数据源一的

package org.javayihao.jpa.dao;
public interface UserDao extends JpaRepository<User,Integer> {
List<User> getUserByAddressEqualsAndIdLessThanEqual(String address, Integer id);
@Query(value = "select * from t_user where id=(select max(id) from t_user)",nativeQuery = true)
User maxIdUser();
}

数据源二的

package org.javayihao.jpa.dao2;
public interface UserDao2 extends JpaRepository<User,Integer> {
List<User> getUserByAddressEqualsAndIdLessThanEqual(String address, Integer id);

@Query(value = "select * from t_user where id=(select max(id) from t_user)",nativeQuery = true)
User maxIdUser();
}

公共的实体类

package org.javayihao.jpa.model;
@Entity(name = "t_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private String address;
//省略getter/setter
}

到此,所有的配置就算完成了,接下来就可以在 Service 中注入不同的 UserDao,不同的 UserDao 操作不同的数据源。

总结

实际开发中如果需求相对而言比较简单可以使用这种多数据源配置,如果分布式中建议首选分布式数据库中间件 MyCat 去解决相关问题,当有数多个数据源,使用使用 MyCat,以及分表策略使用 sharding-by-intfile 比起boot中使用多数据源更加容易。

标签:Spring,spring,Boot,Bean,datasource,数据源,org,DataSource
From: https://blog.51cto.com/u_11334685/5741378

相关文章

  • Spring Boot整合 MyBatis 多数据源
    工程创建首先需要创建MyBatis项目,项目创建和前文的一样,添加MyBatis、MySQL以及Web依赖:pom文件<dependency><groupId>org.springframework.boot</groupId><ar......
  • Springboot中tomcat配置、三大组件配置、拦截器配置
    1.tomcat配置Springboot默认使用的就是嵌入式servlet容器即tomcat,对于web项目,如果使用的是外部tomcat,相关配置比如访问端口、资源路径等可以在tomcat的conf文件下配置。但是......
  • Springboot整合JPA
      概述前面文章记录了Springboot整合Mybatis以及Spingboot整合JDBCTemlate的过程,这篇文章记录Springboot整合JPA操作过程。jpa实际也是用来操作数据库的持久层框架,如何使......
  • Springboot异常处理和自定义错误页面及@ControllerAdvice 注解的三种使用场景!五、@Con
    一、前言springboot默认发生4xx错误时候,pc端响应的页面如下如果是移动端(手机端)将会响应json格式的数据,如下二、Springboot异常处理为什么我们请求错误的路径,boot会给我们返......
  • Springboot整合jsp
    1.创建项目2.选择war工程3.这里可以选择web模块引入(我这里选择的boot版本是2.2.1)4.必须要引入的依赖<dependency><groupId>org.apache.tomcat.embed</groupId><artifa......
  • Springboot整合freemarker
    一、概述FreeMarker是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。它不是面向最终用户的,而是一个Jav......
  • springboot高级——消息队列相关
    写在前边:本文学习尚硅谷的springboot高级整理笔记。消息队列是什么,有什么好处?通过异步处理提高系统性能和削峰、降低系统耦合性。目前使用较多的消息队ActiveMQ,RabbitMQ,Kafk......
  • 《Spring Cloud微服务实战》翟永超(著)
     /*免责声明:全部内容都属于是段友分享,我只是属于整理。**/   /*  写在前边,个人觉得****弄一个积分下载,就是在自掘坟墓。表面上看起来是可以为个人赚积分,实际砍掉分享......
  • springMVC的工作流程
    一.springMVC的常用组件1)DispatcherServlet是一种前端控制器,由框架提供。作用:统一处理请求和响应。除此之外还是整个流程控制的中心,由DispatcherServlet来调用其他组......
  • 【SpringBoot】解决redis 查找/删除缓存失败问题
     使用StringRedisTemplate.delete(key) 删除缓存数据失败,原因是序列化问题导致。 需要把key和hash都使用String的序列化方式 解决方法:创建一个新的配置类:@Con......