Spring Data JPA Single Database - Spring Boot 168 EP 15

Spring Data JPA Single Database – Spring Boot 168 EP 15

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

前言

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

Spring Data JPA

檔案目錄

./
   +- build.gradle
       +- src
           +- main
               +- resources
               |   +- application.properties
               +- java
               |   +- org
               |       +- ruoxue
               |           +- spring_boot_168
               |               +- config
               |                   +- DataSourceConfig.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}"
}

設定 Single Database

application.properties

增加 Datasource 設定。

增加 JPA 設定。

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.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

DataSourceConfig.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.DataSourceAutoConfiguration;
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.context.properties.EnableConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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 = "entityManagerFactory", //
		transactionManagerRef = "transactionManager", //
		basePackages = { //
				"org.ruoxue.spring_boot_168.sso.account.repository", //
		})
@Configuration
@EnableConfigurationProperties
@Slf4j
public class DataSourceConfig extends DataSourceAutoConfiguration {

	@Autowired
	private HibernateProperties hibernateProperties;

	@Autowired
	private JpaProperties jpaProperties;

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

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

	@Primary
	@Bean(name = "dataSource")
	public DataSource dataSource(@Qualifier("hikariConfig") 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;
	}

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

				).persistenceUnit("primaryDatabase")//
				.properties(properties)//
				.build();
	}

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

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

測試

DataSourceConfigTest.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 DataSourceConfigTest {

	@Autowired
	private DataSourceConfig 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", jdbcUrl);
	}
}

config

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

2022-05-22T21:29:16.543+0800 [main] INFO dataSource:65 - poolName: primaryDatabase
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:66 - jdbcUrl: jdbc:mariadb://127.0.0.1:3306/spring_boot_168
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:67 - username: root
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:68 - driverClassName: org.mariadb.jdbc.Driver
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:69 - maximumPoolSize: 100
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:70 - connectionTimeout: 60000
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:71 - maxLifetime: 27800000
2022-05-22T21:29:16.559+0800 [main] INFO dataSource:72 - autoCommit: false
2022-05-22T21: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-22T21:29:16.559+0800 [main] INFO HikariDataSource#<init>:80 - primaryDatabase - Starting...
2022-05-22T21:29:16.606+0800 [main] INFO HikariDataSource#<init>:82 - primaryDatabase - Start completed.

心得分享

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

發佈留言