详解spring boot实现多数据源代码实战
之前在介绍使用JdbcTemplate和Spring-data-jpa时,都使用了单数据源。在单数据源的情况下,SpringBoot的配置非常简单,只需要在application.properties文件中配置连接参数即可。但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,下面基于之前的JdbcTemplate和Spring-data-jpa例子分别介绍两种多数据源的配置方式。
多数据源配置
创建一个Spring配置类,定义两个DataSource用来读取application.properties中的不同配置。如下例子中,主数据源配置为spring.datasource.primary开头的配置,第二数据源配置为spring.datasource.secondary开头的配置。
@Configuration publicclassDataSourceConfig{ @Bean(name="primaryDataSource") @Qualifier("primaryDataSource") @ConfigurationProperties(prefix="spring.datasource.primary") publicDataSourceprimaryDataSource(){ returnDataSourceBuilder.create().build(); } @Bean(name="secondaryDataSource") @Qualifier("secondaryDataSource") @Primary @ConfigurationProperties(prefix="spring.datasource.secondary") publicDataSourcesecondaryDataSource(){ returnDataSourceBuilder.create().build(); } }
对应的application.properties配置如下:
spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1 spring.datasource.primary.username=root spring.datasource.primary.password=root spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2 spring.datasource.secondary.username=root spring.datasource.secondary.password=root spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
JdbcTemplate支持
对JdbcTemplate的支持比较简单,只需要为其注入对应的datasource即可,如下例子,在创建JdbcTemplate的时候分别注入名为primaryDataSource和secondaryDataSource的数据源来区分不同的JdbcTemplate。
@Bean(name="primaryJdbcTemplate") publicJdbcTemplateprimaryJdbcTemplate( @Qualifier("primaryDataSource")DataSourcedataSource){ returnnewJdbcTemplate(dataSource); } @Bean(name="secondaryJdbcTemplate") publicJdbcTemplatesecondaryJdbcTemplate( @Qualifier("secondaryDataSource")DataSourcedataSource){ returnnewJdbcTemplate(dataSource); }
接下来通过测试用例来演示如何使用这两个针对不同数据源的JdbcTemplate。
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Application.class) publicclassApplicationTests{ @Autowired @Qualifier("primaryJdbcTemplate") protectedJdbcTemplatejdbcTemplate1; @Autowired @Qualifier("secondaryJdbcTemplate") protectedJdbcTemplatejdbcTemplate2; @Before publicvoidsetUp(){ jdbcTemplate1.update("DELETEFROMUSER"); jdbcTemplate2.update("DELETEFROMUSER"); } @Test publicvoidtest()throwsException{ //往第一个数据源中插入两条数据 jdbcTemplate1.update("insertintouser(id,name,age)values(?,?,?)",1,"aaa",20); jdbcTemplate1.update("insertintouser(id,name,age)values(?,?,?)",2,"bbb",30); //往第二个数据源中插入一条数据,若插入的是第一个数据源,则会主键冲突报错 jdbcTemplate2.update("insertintouser(id,name,age)values(?,?,?)",1,"aaa",20); //查一下第一个数据源中是否有两条数据,验证插入是否成功 Assert.assertEquals("2",jdbcTemplate1.queryForObject("selectcount(1)fromuser",String.class)); //查一下第一个数据源中是否有两条数据,验证插入是否成功 Assert.assertEquals("1",jdbcTemplate2.queryForObject("selectcount(1)fromuser",String.class)); } }
完整示例:Chapter3-2-3
Spring-data-jpa支持
对于数据源的配置可以沿用上例中DataSourceConfig的实现。
新增对第一数据源的JPA配置,注意两处注释的地方,用于指定数据源对应的Entity实体和Repository定义位置,用@Primary区分主数据源。
新增对第二数据源的JPA配置,内容与第一数据源类似,具体如下:
@Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactorySecondary", transactionManagerRef="transactionManagerSecondary", basePackages={"com.didispace.domain.s"})//设置Repository所在位置 publicclassSecondaryConfig{ @Autowired@Qualifier("secondaryDataSource") privateDataSourcesecondaryDataSource; @Bean(name="entityManagerSecondary") publicEntityManagerentityManager(EntityManagerFactoryBuilderbuilder){ returnentityManagerFactorySecondary(builder).getObject().createEntityManager(); } @Bean(name="entityManagerFactorySecondary") publicLocalContainerEntityManagerFactoryBeanentityManagerFactorySecondary(EntityManagerFactoryBuilderbuilder){ returnbuilder .dataSource(secondaryDataSource) .properties(getVendorProperties(secondaryDataSource)) .packages("com.didispace.domain.s")//设置实体类所在位置 .persistenceUnit("secondaryPersistenceUnit") .build(); } @Autowired privateJpaPropertiesjpaProperties; privateMapgetVendorProperties(DataSourcedataSource){ returnjpaProperties.getHibernateProperties(dataSource); } @Bean(name="transactionManagerSecondary") PlatformTransactionManagertransactionManagerSecondary(EntityManagerFactoryBuilderbuilder){ returnnewJpaTransactionManager(entityManagerFactorySecondary(builder).getObject()); } }
完成了以上配置之后,主数据源的实体和数据访问对象位于:com.didispace.domain.p,次数据源的实体和数据访问接口位于:com.didispace.domain.s。
分别在这两个package下创建各自的实体和数据访问接口
主数据源下,创建User实体和对应的Repository接口
@Entity publicclassUser{ @Id @GeneratedValue privateLongid; @Column(nullable=false) privateStringname; @Column(nullable=false) privateIntegerage; publicUser(){} publicUser(Stringname,Integerage){ this.name=name; this.age=age; } //省略getter、setter } publicinterfaceUserRepositoryextendsJpaRepository{ }
从数据源下,创建Message实体和对应的Repository接口
@Entity publicclassMessage{ @Id @GeneratedValue privateLongid; @Column(nullable=false) privateStringname; @Column(nullable=false) privateStringcontent; publicMessage(){} publicMessage(Stringname,Stringcontent){ this.name=name; this.content=content; } //省略getter、setter } publicinterfaceMessageRepositoryextendsJpaRepository{ }
接下来通过测试用例来验证使用这两个针对不同数据源的配置进行数据操作。
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Application.class) publicclassApplicationTests{ @Autowired privateUserRepositoryuserRepository; @Autowired privateMessageRepositorymessageRepository; @Test publicvoidtest()throwsException{ userRepository.save(newUser("aaa",10)); userRepository.save(newUser("bbb",20)); userRepository.save(newUser("ccc",30)); userRepository.save(newUser("ddd",40)); userRepository.save(newUser("eee",50)); Assert.assertEquals(5,userRepository.findAll().size()); messageRepository.save(newMessage("o1","aaaaaaaaaa")); messageRepository.save(newMessage("o2","bbbbbbbbbb")); messageRepository.save(newMessage("o3","cccccccccc")); Assert.assertEquals(3,messageRepository.findAll().size()); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。