Spring Boot 整合多数据源

编程入门 行业动态 更新时间:2024-10-10 11:22:26

<a href=https://www.elefans.com/category/jswz/34/1769862.html style=Spring Boot 整合多数据源"/>

Spring Boot 整合多数据源

一、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.DruidDataSourcespring.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 {@BeanJdbcTemplate jdbcTemplateOne(@Qualifier("dsOne") DataSource dsOne) {return new JdbcTemplate(dsOne);}@BeanJdbcTemplate 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.DruidDataSourcespring.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;@BeanSqlSessionFactory sqlSessionFactory1() {SqlSessionFactory sessionFactory = null;try {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dsOne);sessionFactory = bean.getObject();} catch (Exception e) {e.printStackTrace();}return sessionFactory;}@BeanSqlSessionTemplate 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;@BeanSqlSessionFactory sqlSessionFactory2() {SqlSessionFactory sessionFactory = null;try {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dsTwo);sessionFactory = bean.getObject();} catch (Exception e) {e.printStackTrace();}return sessionFactory;}@BeanSqlSessionTemplate 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 mapperPUBLIC "-//mybatis//DTD Mapper 3.0//EN"".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 mapperPUBLIC "-//mybatis//DTD Mapper 3.0//EN"".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")@PrimaryDataSource 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;@AutowiredJpaProperties jpaProperties;@Bean@PrimaryLocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {return builder.dataSource(dsOne).packages("org.javayihao.jpa.model").properties(jpaProperties.getProperties()).persistenceUnit("pu1").build();}@BeanPlatformTransactionManager 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;@AutowiredJpaProperties jpaProperties;@BeanLocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) {return builder.dataSource(dsTwo).packages("org.javayihao.jpa.model").properties(jpaProperties.getProperties()).persistenceUnit("pu2").build();}@BeanPlatformTransactionManager 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 Boot 整合多数据源

本文发布于:2024-03-23 23:22:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1744059.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Spring   Boot

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!