摘要:项目中用到多个数据库时,比如一个外网库,一个内网库,从而我们需要配置多个数据源,接下来介绍一下SpringBoot多数据源配置,上篇介绍了单数据源使用jdbctemplate访问数据库,springboot使用jdbctemplate访问数据库
![abcefbfef381013ac3f2fcee5589506f.png](https://i-blog.csdnimg.cn/blog_migrate/0b56f8d4697415380a12cc16ce21bb73.jpeg)
用到的注解介绍
@ConfigurationProperties
读取Spring的配置文件
@Resource
默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来注入。
它有两个属性是比较重要的:
name: Spring 将 name 的属性值解析为 bean 的名称, 使用 byName 的自动注入策略
type: Spring 将 type的属性值解析为 bean 的类型,使用 byType 的自动注入策略
注: 如果既不指定 name 属性又不指定 type 属性,Spring这时通过反射机制使用 byName 自动注入策略
@Resource的装配顺序
- 如果同时指定了 name 属性和 type 属性,那么 Spring 将从容器中找唯一匹配的 bean 进行装配,找不到则抛出异常
- 如果指定了 name 属性值,则从容器中查找名称匹配的 bean 进行装配,找不到则抛出异常
- 如果指定了 type 属性值,则从容器中查找类型匹配的唯一的 bean 进行装配,找不到或者找到多个都会抛出异常
- 如果都不指定,则会自动按照 byName 方式进行装配, 如果没有匹配,则回退一个原始类型进行匹配,如果匹配则自动装配
@Autowired
默认是按照类型进行装配注入,默认情况下,它要求依赖对象必须存在,如果允许 null 值,可以设置它 required 为false。
如果我们想要按名称进行装配的话,可以添加一个 @Qualifier 注解解决。
@Primary
在众多相同的bean中,优先使用用@Primary注解的bean.
@Qualifier
搭配@Autowired使用,可以让Spring可以按照Bean名称进入注入
![3e79871b491244b8ae66926e745fa8dc.png](https://i-blog.csdnimg.cn/blog_migrate/647e8210156ba7450fc282b2d27979ce.jpeg)
多数据源配置:
application.properties中添加多个数据源的配置信息,这边测试我就加了两个数据源代码:
spring.application.name=testserver.port=8088#多数据源配置#第一个数据源spring.datasource.primary.url=jdbc:mysql://127.0.0.1:3306/db1spring.datasource.primary.username=rootspring.datasource.primary.password=root#连接驱动过时了#spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver##第二个数据源spring.datasource.secondary.url=jdbc:mysql://127.0.0.1:3306/db2spring.datasource.secondary.username=rootspring.datasource.secondary.password=root#连接驱动过时了#spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
数据源的配置类,创建JdbcTemplate的时候注入不同的数据源来区分不同的JdbcTemplate
package com.mundo.Test.datasource;import javax.sql.DataSource;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.core.JdbcTemplate;import com.alibaba.druid.pool.DruidDataSource;@Configurationpublic class PrimaryDataSourceConfig {@Bean(name = "primaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.primary") // 配置文件中配置的数据源前缀@Primary // 相同的bean中,优先使用@Primarypublic DataSource primaryDataSource() {// 指定使用DruidDataSourcereturn DataSourceBuilder.create().type(DruidDataSource.class).build();}@Bean(name = "primaryJdbcTemplate")public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) {return new JdbcTemplate(dataSource);}}
package com.mundo.Test.datasource;import javax.sql.DataSource;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.core.JdbcTemplate;import com.alibaba.druid.pool.DruidDataSource;@Configurationpublic class SecondaryDatasourceConfig {@Bean(name = "secondaryDataSource")@Qualifier("secondaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {// 指定使用DruidDataSourcereturn DataSourceBuilder.create().type(DruidDataSource.class).build();}@Bean(name = "secondaryJdbcTemplate")public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {return new JdbcTemplate(dataSource);}}
单元测试:
package com.mundo.Test;import java.util.List;import java.util.Map;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.test.context.junit4.SpringRunner;import com.alibaba.fastjson.JSONObject;@RunWith(SpringRunner.class)@SpringBootTestpublic class TestMandDatasource {@Autowired@Qualifier("primaryJdbcTemplate")private JdbcTemplate primary;@Autowired@Qualifier("secondaryJdbcTemplate")private JdbcTemplate secondary;@Testpublic void test() {// 第一个数据源List> list1 = primary.queryForList("select * from user");System.out.println(JSONObject.toJSONString(list1));// 第二个数据源List> list2 = secondary.queryForList("select * from computer");System.out.println(JSONObject.toJSONString(list2));}}
![bb326663029485bf46b689cf6d9f9cd7.png](https://i-blog.csdnimg.cn/blog_migrate/43cce73f412c236595280614bf3dbdd7.jpeg)
容易出错的地方:@Primary注解的使用,两个数据源都是使用了@Primary注解就会出现下面这个错误:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: more than one 'primary' bean found among candidates: [primaryDataSource, secondaryDataSource]at org.springframework.beans.factory.support.DefaultListableBeanFactory.determinePrimaryCandidate(DefaultListableBeanFactory.java:1370) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1028) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:344) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1092) ~[spring-context-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.init(DataSourceInitializer.java:77) ~[spring-boot-autoconfigure-1.5.19.RELEASE.jar:1.5.19.RELEASE]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_66]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_66]at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_66]at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ~[spring-beans-4.3.22.RELEASE.jar:4.3.22.RELEASE]... 54 common frames omitted
![455e091466b862ddb91c8e679be0c997.png](https://i-blog.csdnimg.cn/blog_migrate/9bb1a05e250c4a66699bf6bec950692b.jpeg)
每天进步一点点,前进不止一小点,你侬我侬不如码农,欢迎关注转发评论!