摘要:项目中用到多个数据库时,比如一个外网库,一个内网库,从而我们需要配置多个数据源,接下来介绍一下SpringBoot多数据源配置,上篇介绍了单数据源使用jdbctemplate访问数据库,springboot使用jdbctemplate访问数据库
用到的注解介绍
@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名称进入注入
多数据源配置:
application.properties中添加多个数据源的配置信息,这边测试我就加了两个数据源代码:
spring.application.name=test server.port=8088 #多数据源配置 #第一个数据源 spring.datasource.primary.url=jdbc:mysql://127.0.0.1:3306/db1 spring.datasource.primary.username=root spring.datasource.primary.password=root #连接驱动过时了 #spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver # #第二个数据源 spring.datasource.secondary.url=jdbc:mysql://127.0.0.1:3306/db2 spring.datasource.secondary.username=root spring.datasource.secondary.password=root #连接驱动过时了 #spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.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; @Configuration public class PrimaryDataSourceConfig { @Bean(name = "primaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.primary") // 配置文件中配置的数据源前缀 @Primary // 相同的bean中,优先使用@Primary public DataSource primaryDataSource() { // 指定使用DruidDataSource return 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; @Configuration public class SecondaryDatasourceConfig { @Bean(name = "secondaryDataSource") @Qualifier("secondaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { // 指定使用DruidDataSource return 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) @SpringBootTest public class TestMandDatasource { @Autowired @Qualifier("primaryJdbcTemplate") private JdbcTemplate primary; @Autowired @Qualifier("secondaryJdbcTemplate") private JdbcTemplate secondary; @Test public void test() { // 第一个数据源 List<Map<String, Object>> list1 = primary.queryForList("select * from user"); System.out.println(JSONObject.toJSONString(list1)); // 第二个数据源 List<Map<String, Object>> list2 = secondary.queryForList("select * from computer"); System.out.println(JSONObject.toJSONString(list2)); } }
容易出错的地方:@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
每天进步一点点,前进不止一小点,你侬我侬不如码农,欢迎关注转发评论!
本文暂时没有评论,来添加一个吧(●'◡'●)