Spring Boot2.4双数据源的配置

相较于单数据源,双数据源配置有时候在数据分库的时候可能更加有利
但是在参考诸多博客以及书籍(汪云飞的实战书)的时候,发现对于spring boot1.X是完全没问题的,一旦切换到spring boot2.X的时候,就会报出无法实例化出数据源对象等各种问题。我猜测这是无法很好的读取到数据源配置信息的关系。
目前来说,官方文档示例比较好的解决了这个问题

配置双数据源

这里使用java配置方式,需要注意以下几点:

  • 主数据源要加上@Primary注解
  • 需要通过构建DataSourceProperties这个Bean来构建一个数据源,这也是官方文档的示例配置方式,如果采用1.X的方式,很可能会报出jdbcUrl is required with driverClassName这个错误,之后的DataSourceBean,EntityFactoryBean等都会无法实例化
@Configuration
public class DataSourceConfig {
    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.primary")
    public DataSourceProperties firstDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(name = "primaryDataSource")
    @Primary
    @ConfigurationProperties("app.datasource.primary")
    public DataSource primaryDataSource() {
        return firstDataSourceProperties().initializeDataSourceBuilder().build();
    }

    @Bean
    @ConfigurationProperties("app.datasource.secondary")
    public DataSourceProperties secondDataSourceProperties() {
        return new DataSourceProperties();
    }


    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties("app.datasource.secondary")
    public DataSource secondaryDataSource() {
        return secondDataSourceProperties().initializeDataSourceBuilder().build();
    }
}

配置yml文件

就是在application.yml文件里写一些数据库的配置信息,这个应该都比较轻车熟路了。关于是使用propertiesyml方式,看个人习惯

spring:
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
app:
  datasource:
    primary:
      url: jdbc:mysql://localhost:3306/kpimanage
      username: root
      password: root123
      maximum-pool-size: 30
      driver-class-name: com.mysql.jdbc.Driver
    secondary:
      url: jdbc:mysql://localhost:3306/local
      username: root
      password: root123
      maximum-pool-size: 30
      driver-class-name: com.mysql.jdbc.Driver

配置Spring Jpa

主要是以下几点:

  • 启动事务管理
  • 定义entity包。也可以不定义,使用默认扫描的方式
  • 定义repository包。也可以不定义,使用默认扫描的方式
  • 自定义EntiryManagerFactoryBean
  • 注意这里只是对使用spring data jpa来说有用,如果使用mybatis的话,根据自身情况配置,这里的配置完全不适用
@Configuration
@EnableTransactionManagement//开启事务管理
@EnableJpaRepositories(basePackages = "com.luzj.dblsource.repository.primary",
entityManagerFactoryRef = "entityManagerFactoryPrimary",
transactionManagerRef = "transactionManagerPrimary")//jpa 配置>repository位置,实体管理Factory配置,事务管理配置
public class PrimaryConfig {

    @Autowired @Qualifier("primaryDataSource")
    DataSource primaryDataSource;

    // 自定义EntityManagerFactory
    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)
                .packages("com.luzj.dblsource.entity.primary") //设置实体类所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }

    //自定义EntityManager
    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    //自定义TransactionManager
    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryPrimary(builder).getObject());
        return transactionManager;
    }
}

同时,第二数据源也如此配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.luzj.dblsource.repository.secondary",
entityManagerFactoryRef = "entityManagerFactorySecondary",
transactionManagerRef = "transactionManagerSecondary")
public class SecondaryConfig {
//...
}

测试

配置基本到此结束,下面分别在两个数据库建立不同的table,然后使用repository对表进行操作,看是否能够顺利运行

primary数据库建立Person表以及repository

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Integer id;

    private String address;

    private Integer age;

    private String name;
    //setter getter...
}
public interface PersonRepository extends JpaRepository<Person,Integer> {
}

secondary数据库建立code_river表

@Entity
@Table(name = "code_river")
public class CodeRiver {
    @Id
    @Column(name = "river_id")
    private String id;

    @Column(name = "river_desc")
    private String riverDesc;
    //setter getter ...
}
public interface CodeRiverRepository extends JpaRepository<CodeRiver,String> {
}

单元测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class DblsourceApplicationTests {

	@Test
	public void contextLoads() {
	}
	@Autowired
	private PersonRepository personRepository;
	@Autowired
	private CodeRiverRepository codeRiverRepository;

	@Test
	public void test(){
		personRepository.save(new Person("湖南",23,"章邯"));
		personRepository.save(new Person("纽约",27,"john"));
		personRepository.save(new Person("香港",43,"张一山"));
		personRepository.save(new Person("北京",44,"张朝阳"));
		personRepository.save(new Person("深圳",53,"马化腾"));

		Assert.assertEquals(5,personRepository.findAll().size());

		codeRiverRepository.save(new CodeRiver("area110","阿姆斯特朗回旋加速过海"));
		Assert.assertEquals(1,codeRiverRepository.findAll().size());
	}
}

img

小结

主要介绍了在springboot 2.4环境下多数据源的配置方式
代码地址

参考

posted @   小小怪医芙兰  阅读(1065)  评论(0编辑  收藏  举报
编辑推荐:
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
阅读排行:
· C# 中比较实用的关键字,基础高频面试题!
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
· AI Agent爆火后,MCP协议为什么如此重要!
点击右上角即可分享
微信分享提示