Spring Data JPA Multiple Databases - Spring Boot 168 EP 16

Spring Data JPA Multiple Databases – Spring Boot 168 EP 16

提供了一種物件與關聯映射工具來管理 Java 應用中的關係資料,用極簡的代碼就能實現對資料庫的操作訪問,實現了多資料庫的設定, EP 16 增加了相依套件及範例,並透過 JUnit 5 單元測試來驗證產出結果。

前言

MariaDB 是一個關聯式資料庫,由 MySQL 原始開發人員建立的一個分支,源於與 MySQL 被 Oracle 收購有關的擔憂。它支援小資料處理任務和企業需求, 目標是成為 MySQL 的替代品。.

Spring Data JPA

檔案目錄

./
   +- build.gradle
       +- src
           +- main
               +- resources
               |   +- application.properties
               +- java
               |   +- org
               |       +- ruoxue
               |           +- spring_boot_168
               |               +- config
               |                   +- LogDataSourceConfig.java   

Gradle

build.gradle

增加 Spring Boot Starter Data JPA 

增加 MariaDB Java Client 

修改完後,點右鍵,Gradle -> Refresh Gradle Project 。

buildscript {
	group 'org.ruoxue.spring-boot-168'
	version = '0.0.1-SNAPSHOT'
	ext {
		springBootVersion = '2.1.7.RELEASE'
		mariadbJavaClientVersion = '2.4.3'
	}
}

dependencies {
	implementation "org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}"
	implementation "org.mariadb.jdbc:mariadb-java-client:${mariadbJavaClientVersion}"
}

設定 Multiple Databases

application.properties

增加 Datasource 設定。

spring.datasource.hikari.jdbc-url=jdbc:mariadb://127.0.0.1:3306/spring_boot_168
spring.datasource.hikari.username=root
spring.datasource.hikari.password=1111
spring.datasource.hikari.driver-class-name=org.mariadb.jdbc.Driver

spring.datasource.hikari.pool-name=primaryDatabase
spring.datasource.hikari.maximum-pool-size=100
spring.datasource.hikari.minimum-idle=8
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.max-lifetime=27800000
spring.datasource.hikari.auto-commit=false

spring.datasource.log.hikari.jdbc-url=jdbc:mariadb://127.0.0.1:3306/spring_boot_168_log
spring.datasource.log.hikari.username=root
spring.datasource.log.hikari.password=1111
spring.datasource.log.hikari.driver-class-name=org.mariadb.jdbc.Driver

spring.datasource.log.hikari.pool-name=logDatabase
spring.datasource.log.hikari.maximum-pool-size=100
spring.datasource.log.hikari.minimum-idle=8
spring.datasource.log.hikari.idle-timeout=600000
spring.datasource.log.hikari.connection-timeout=60000
spring.datasource.log.hikari.max-lifetime=27800000
spring.datasource.log.hikari.auto-commit=false

spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.jdbc.batch_size=10
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates =true

LogDataSourceConfig.java

新增檔案。

package org.ruoxue.spring_boot_168.config;

import java.util.Map;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import lombok.extern.slf4j.Slf4j;

@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "logEntityManagerFactory", //
		transactionManagerRef = "logTransactionManager", //
		basePackages = { //
				"org.ruoxue.spring_boot_168.sso.account_log.repository", //
		})
@Configuration
@Slf4j
public class LogDataSourceConfig {

	@Autowired
	private HibernateProperties hibernateProperties;

	@Autowired
	private JpaProperties jpaProperties;

	@Bean(name = "logDataSourceProperties")
	@ConfigurationProperties(prefix = "spring.datasource.log.hikari")
	public DataSourceProperties dataSourceProperties() {
		return new DataSourceProperties();
	}

	@Bean(name = "logHikariConfig")
	@ConfigurationProperties(prefix = "spring.datasource.log.hikari")
	public HikariConfig hikariConfig() {
		HikariConfig hikariConfig = new HikariConfig();
		return hikariConfig;
	}

	@Bean(name = "logDataSource")
	public DataSource dataSource(@Qualifier("logHikariConfig") HikariConfig hikariConfig) {
		log.info("poolName: " + hikariConfig.getPoolName());
		log.info("jdbcUrl: " + hikariConfig.getJdbcUrl());
		log.info("username: " + hikariConfig.getUsername());
		log.info("driverClassName: " + hikariConfig.getDriverClassName());
		log.info("maximumPoolSize: " + hikariConfig.getMaximumPoolSize());
		log.info("connectionTimeout: " + hikariConfig.getConnectionTimeout());
		log.info("maxLifetime: " + hikariConfig.getMaxLifetime());
		log.info("autoCommit: " + hikariConfig.isAutoCommit());
		log.info("jpaProperties: " + jpaProperties.getProperties());
		DataSource dataSource = new HikariDataSource(hikariConfig);
		return dataSource;
	}

	@Bean(name = "logEntityManagerFactory")
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
			@Qualifier("logDataSource") DataSource dataSource) {
		Map<String, Object> properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),
				new HibernateSettings());
		return builder.dataSource(dataSource)//
				.packages( //
						"org.ruoxue.spring_boot_168.sso.account_log.model"//
				).persistenceUnit("logDatabase")//
				.properties(properties)//
				.build();
	}

	@Bean(name = "logTransactionManager")
	public PlatformTransactionManager transactionManager(
			@Qualifier("logEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
		return new JpaTransactionManager(entityManagerFactory);
	}

	@Bean(name = "logJdbcTemplate")
	public JdbcTemplate jdbcTemplate(@Qualifier("logDataSource") DataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}
}

測試

LogDataSourceConfigTest.java

新增單元測試,驗證是否符合預期 。

package org.ruoxue.spring_boot_168.config;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.ruoxue.spring_boot_168.Application;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.zaxxer.hikari.HikariConfig;

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class LogDataSourceConfigTest {

	@Autowired
	private LogDataSourceConfig config;

	@Test
	public void config() {
		assertNotNull(config);
		HikariConfig hikariConfig = config.hikariConfig();
		String jdbcUrl = hikariConfig.getJdbcUrl();
		assertEquals("jdbc:mariadb://127.0.0.1:3306/spring_boot_168_log", jdbcUrl);
	}
}

config

測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console 。

2022-05-25T21:29:16.543+0800 [main] INFO dataSource:65 - poolName: primaryDatabase
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:66 - jdbcUrl: jdbc:mariadb://127.0.0.1:3306/spring_boot_168
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:67 - username: root
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:68 - driverClassName: org.mariadb.jdbc.Driver
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:69 - maximumPoolSize: 100
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:70 - connectionTimeout: 60000
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:71 - maxLifetime: 27800000
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:72 - autoCommit: false
2022-05-25T21:29:16.559+0800 [main] INFO dataSource:73 - jpaProperties: {hibernate.jdbc.batch_versioned_data=true, hibernate.order_updates=true, hibernate.jdbc.batch_size=10, hibernate.order_inserts=true}
2022-05-25T21:29:16.559+0800 [main] INFO HikariDataSource#&lt;init&gt;:80 - primaryDatabase - Starting...
2022-05-25T21:29:16.606+0800 [main] INFO HikariDataSource#&lt;init&gt;:82 - primaryDatabase - Start completed.
2022-05-25T21:29:16.640+0800 [main] INFO dataSource:61 - poolName: logDatabase
2022-05-25T21:29:16.640+0800 [main] INFO dataSource:62 - jdbcUrl: jdbc:mariadb://127.0.0.1:3306/spring_boot_168_log
2022-05-25T21:29:16.640+0800 [main] INFO dataSource:63 - username: root
2022-05-25T21:29:16.641+0800 [main] INFO dataSource:64 - driverClassName: org.mariadb.jdbc.Driver
2022-05-25T21:29:16.641+0800 [main] INFO dataSource:65 - maximumPoolSize: 100
2022-05-25T21:29:16.641+0800 [main] INFO dataSource:66 - connectionTimeout: 60000
2022-05-25T21:29:16.642+0800 [main] INFO dataSource:67 - maxLifetime: 27800000
2022-05-25T21:29:16.642+0800 [main] INFO dataSource:68 - autoCommit: false
2022-05-25T21:29:16.642+0800 [main] INFO dataSource:69 - jpaProperties: {hibernate.jdbc.batch_versioned_data=true, hibernate.order_updates=true, hibernate.jdbc.batch_size=10, hibernate.order_inserts=true}
2022-05-25T21:29:16.643+0800 [main] INFO HikariDataSource#&lt;init&gt;:80 - logDatabase - Starting...
2022-05-25T21:29:16.645+0800 [main] INFO HikariDataSource#&lt;init&gt;:82 - logDatabase - Start completed.

心得分享

實現多資料庫的連線池,設定連線池最大與最小連線數限制,及取得連線逾時,閒置逾時等功能,讓資料庫連線更有效率,節省系統資源的耗用。

發佈留言