Spring Data MongoDB Single Database - Spring Boot 168 EP 19

Spring Data MongoDB Single Database – Spring Boot 168 EP 19

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

前言

MongoDB 是一個 NoSQL 文檔型的資料庫,適合存取非結構資料,類似於 JSON 格式,可以包含其他文檔,其動態建模的特性使得它更加自由靈活,分片的資料分散處理架構,可以透過水平擴充儲存海量資料,因此適用於各種應用場景如事件紀錄、電子商務、手機應用等。

Spring Data MongoDB

檔案目錄

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

Gradle

build.gradle

增加 Spring Boot Starter Data MongoDB 。

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

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

dependencies {
	implementation "org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}"
}

設定 Single Database

application.properties

增加 Mongodb 設定。

spring.data.mongodb.custom.uri=mongodb://root:1111@127.0.0.1:27017/spring_boot_168?authSource=admin
spring.data.mongodb.custom.connectionsPerHost=100
spring.data.mongodb.custom.minConnectionsPerHost=8
spring.data.mongodb.custom.retryWrites=true  
spring.data.mongodb.custom.connectTimeout=60000
spring.data.mongodb.custom.socketTimeout=60000  
spring.data.mongodb.custom.maxConnectionIdleTime=28800000  
spring.data.mongodb.custom.maxConnectionLifeTime=28800000 
spring.data.mongodb.custom.maxWaitTime=60000

MongoDBConfig.java

新增檔案。

package org.ruoxue.spring_boot_168.config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientOptions.Builder;

import lombok.extern.slf4j.Slf4j;

import com.mongodb.MongoClientURI;

@EnableMongoRepositories(mongoTemplateRef = "mongoTemplate", //
		basePackages = { //
				"org.ruoxue.spring_boot_168.chat.chat_message.repository, " //
		})
@Configuration
@Slf4j
public class MongoDBConfig {

	@Value("${spring.data.mongodb.custom.uri}")
	private String uri;

	@Value("${spring.data.mongodb.custom.connectionsPerHost}")
	private int connectionsPerHost;

	@Value("${spring.data.mongodb.custom.minConnectionsPerHost}")
	private int minConnectionsPerHost;

	@Value("${spring.data.mongodb.custom.retryWrites}")
	private boolean retryWrites;

	@Value("${spring.data.mongodb.custom.connectTimeout}")
	private int connectTimeout;

	@Value("${spring.data.mongodb.custom.socketTimeout}")
	private int socketTimeout;

	@Value("${spring.data.mongodb.custom.maxConnectionIdleTime}")
	private int maxConnectionIdleTime;

	@Value("${spring.data.mongodb.custom.maxConnectionLifeTime}")
	private int maxConnectionLifeTime;

	@Value("${spring.data.mongodb.custom.maxWaitTime}")
	private int maxWaitTime;

	@Primary
	@Bean(name = "mongoBuilder")
	public Builder mongoBuilder() {
		Builder builder = MongoClientOptions.builder();
		builder.connectionsPerHost(this.connectionsPerHost);
		builder.minConnectionsPerHost(this.minConnectionsPerHost);
		builder.retryWrites(this.retryWrites);
		builder.connectTimeout(this.connectTimeout);
		builder.socketTimeout(this.socketTimeout);
		builder.maxConnectionIdleTime(this.maxConnectionIdleTime);
		builder.maxConnectionLifeTime(this.maxConnectionLifeTime);
		builder.maxWaitTime(this.maxWaitTime);
		log.info("uri: " + this.uri);
		log.info("connectionsPerHost: " + this.connectionsPerHost);
		return builder;
	}

	@Primary
	@Bean(name = "mongoClientURI")
	public MongoClientURI mongoClientURI(@Qualifier("mongoBuilder") Builder builder) {
		MongoClientURI mongoClientURI = new MongoClientURI(this.uri, builder);
		return mongoClientURI;
	}

	@Primary
	@Bean(name = "mongoClient")
	public MongoClient mongoClient(@Qualifier("mongoClientURI") MongoClientURI mongoClientURI) {
		MongoClient mongoClient = new MongoClient(mongoClientURI);
		return mongoClient;
	}

	@Primary
	@Bean(name = "mongoDbFactory")
	public MongoDbFactory mongoDbFactory(@Qualifier("mongoClientURI") MongoClientURI mongoClientURI) {
		return new SimpleMongoDbFactory(mongoClientURI);
	}

	@Primary
	@Bean(name = "mongoTemplate")
	public MongoTemplate mongoTemplate(@Qualifier("mongoDbFactory") MongoDbFactory mongoDbFactory) {
		DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
		MongoMappingContext mongoMappingContext = new MongoMappingContext();
		mongoMappingContext.setFieldNamingStrategy(new SnakeCaseFieldNamingStrategy());
		MongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
		MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, mongoConverter);
		return mongoTemplate;

	}
}

測試

MongoDBConfigTest.java

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

package org.ruoxue.spring_boot_168.config;

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;

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

	@Autowired
	private MongoDBConfig config;

	@Test
	public void config() {
		assertNotNull(config);
	}
}

config

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

2022-06-03T23:17:42.458+0800 [main] INFO mongoBuilder:75 - uri: mongodb://root:1111@127.0.0.1:27017/spring_boot_168?authSource=admin
2022-06-03T23:17:42.459+0800 [main] INFO mongoBuilder:76 - connectionsPerHost: 100
2022-06-03T00:17:42.927+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:3}] to 127.0.0.1:27017
2022-06-03T00:17:42.927+0800 [main] INFO cluster#info:71 - Cluster created with settings {hosts=[127.0.0.1:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2022-06-03T00:17:42.931+0800 [cluster-ClusterId{value='635ff1b6c313272ee09f12e2', description='null'}-127.0.0.1:27017] INFO connection#info:71 - Opened connection [connectionId{localValue:6}] to 127.0.0.1:27017
2022-06-03T00:17:42.931+0800 [cluster-ClusterId{value='635ff1b6c313272ee09f12e2', description='null'}-127.0.0.1:27017] INFO cluster#info:71 - Monitor thread successfully connected to server with description ServerDescription{address=127.0.0.1:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[6, 0, 2]}, minWireVersion=0, maxWireVersion=17, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=526811}
2022-06-03T00:17:42.934+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:4}] to 127.0.0.1:27017
2022-06-03T00:17:42.938+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:7}] to 127.0.0.1:27017
2022-06-03T00:17:42.942+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:8}] to 127.0.0.1:27017
2022-06-03T00:17:42.946+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:9}] to 127.0.0.1:27017
2022-06-03T00:17:42.951+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:10}] to 127.0.0.1:27017
2022-06-03T00:17:42.954+0800 [MaintenanceTimer-1-thread-1] INFO connection#info:71 - Opened connection [connectionId{localValue:11}] to 127.0.0.1:27017

心得分享

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

發佈留言