Spring Boot MongoDB

歡迎來到Spring Boot MongoDB範例。 Spring Boot是快速啟動Spring項目的最簡單方式,而MongoDB是最流行的NoSQL數據庫。 讓我們看看如何將Spring與MongoDB數據庫集成。

Spring Boot MongoDB

我們需要以下API來處理Spring Boot和MongoDB數據庫。

  • Spring Data MongoDB
  • Spring Boot

有兩種方法可以連接到MongoDB數據庫 – MongoRepositoryMongoTemplate。 我們將試圖確定一個API在另一個API上提供了什麼,以及何時應該選擇其中之一來解決您的用例。 我們將使用Spring Initializr工具快速設置項目。 所以,讓我們開始吧。

Spring Boot MongoDB項目設置

我們將使用Spring Initializr工具快速設置項目。 我們只會使用以下兩個依賴項: 下載項目並解壓縮它。 然後將其導入到您喜歡的IDE – Eclipse或IntelliJ IDEA中。

Maven 依賴

雖然我們已經使用工具完成了設置,但如果你想手動設置,我們在這個專案中使用 Maven 構建系統,這是我們使用的相關依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.journaldev.spring</groupId>
	<artifactId>spring-boot-mongodb</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-boot-mongodb</name>
	<description>Spring Boot MongoDB Example</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

確保從 Maven 中央庫中使用穩定版本的 Spring Boot

Spring Boot MongoDB 模型類

我們有一個簡單的模型類 User.java

package com.journaldev.bootifulmongodb.model;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class User {

	@Id
	private String userId;
	private String name;
	private Date creationDate = new Date();
	private Map<String, String> userSettings = new HashMap<>();

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Date creationDate) {
		this.creationDate = creationDate;
	}

	public Map<String, String> getUserSettings() {
		return userSettings;
	}

	public void setUserSettings(Map<String, String> userSettings) {
		this.userSettings = userSettings;
	}
}

Spring Boot MongoDB API

在我們的應用程序中,將具有以下功能和數據庫交互。

  • 獲取所有用戶
  • 通過 ID 獲取用戶
  • 獲取用戶設置
  • 從地圖中獲取特定鍵
  • 添加/更新用戶設置

Spring Data MongoDB – MongoRepository

現在我們將使用 Spring Data MongoDB 存儲庫來訪問我們的數據。Spring Data MongoRepository 為我們提供了常用功能,我們可以輕鬆插入並使用它。讓我們定義我們的 Repository 介面。

package com.journaldev.bootifulmongodb.dal;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import com.journaldev.bootifulmongodb.model.User;

@Repository
public interface UserRepository extends MongoRepository<User, String> {
}

定義 MongoDB 屬性

在我們編寫控制器之前,重要的是我們與本地 MongoDB 實例建立連接。我們將使用 Spring Boot 屬性來完成這個任務。

# 本地 MongoDB 配置
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=user_db
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost

# 應用配置
server.port=8102
spring.application.name=BootMongo
server.context-path=/user

因此,應用將運行在8102端口,並連接到提供的認證的本地 MongoDB 實例。如果您有一個沒有啟用授權的本地實例,您可以刪除配置的前三行。

定義 Spring 控制器

最後,讓我們轉向創建我們的 Controller 類。

package com.journaldev.bootifulmongodb.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.journaldev.bootifulmongodb.dal.UserRepository;
import com.journaldev.bootifulmongodb.model.User;

@RestController
@RequestMapping(value = "/")
public class UserController {

	private final Logger LOG = LoggerFactory.getLogger(getClass());

	private final UserRepository userRepository;

	public UserController(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
}

我們剛剛自動裝配了存儲庫介面依賴,接下來將使用它。

定義API

對於我們提到的功能,我們現在將制定API並訪問userRepository依賴,該依賴將在內部使用Spring Data MongoRepository API。請注意,我們不必在介面中編寫任何數據庫交互代碼,因為Spring Data為我們完成了全部工作。

獲取所有用戶

@RequestMapping(value = "", method = RequestMethod.GET)
public List<User> getAllUsers() {
	LOG.info("Getting all users.");
	return userRepository.findAll();
}

findAll()只是Spring Data MongoRepository內部提供的一個方法。

按ID獲取用戶

現在,讓我們按ID獲取特定用戶。

@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
	LOG.info("Getting user with ID: {}.", userId);
	return userRepository.findOne(userId);
}

findOne()只是Spring Data MongoRepository內部提供的一個方法,用於按ID獲取對象。

添加新用戶

我們將在下面的函數中添加一個新用戶。

@RequestMapping(value = "/create", method = RequestMethod.POST)
public User addNewUsers(@RequestBody User user) {
	LOG.info("Saving user.");
	return userRepository.save(user);
}

獲取用戶設置

現在,我們已將示例數據添加到數據庫中,讓我們嘗試提取其中的一部分。

@RequestMapping(value = "/settings/{userId}", method = RequestMethod.GET)
public Object getAllUserSettings(@PathVariable String userId) {
	User user = userRepository.findOne(userId);
	if (user != null) {
		return user.getUserSettings();
	} else {
		return "User not found.";
	}
}

獲取特定用戶設置

@RequestMapping(value = "/settings/{userId}/{key}", method = RequestMethod.GET)
public String getUserSetting(@PathVariable String userId, @PathVariable String key) {
	User user = userRepository.findOne(userId);
	if (user != null) {
		return user.getUserSettings().get(key);
	} else {
		return "User not found.";
	}
}

請注意,在上面的查詢中,我們獲得了用戶對象,然後提取了完整的設置映射(其中可能包含1000個對象),最後獲得了我們自己的值。當我們將其用作直接API時,這是Spring Data查詢的一個缺點。

添加新用戶設置

讓我們試著為現有用戶添加一些數據:

@RequestMapping(value = "/settings/{userId}/{key}/{value}", method = RequestMethod.GET)
public String addUserSetting(@PathVariable String userId, @PathVariable String key, @PathVariable String value) {
	User user = userRepository.findOne(userId);
	if (user != null) {
		user.getUserSettings().put(key, value);
		userRepository.save(user);
		return "Key added";
	} else {
		return "User not found.";
	}
}

通過我們編寫的所有代碼,顯然我們除了定義存儲庫接口和自動連線依賴項之外,根本不需要寫一行代碼來訪問數據庫。這是 Spring Data MongoRepository API 提供給我們的便利,但它也有一些缺點。我們將在定義 MongoTemplate 版本後進一步闡述這一點。讓我們也開始吧。

Spring Data MongoDB – MongoTemplate

我們將在這裡定義 MongoTemplate 數據庫查詢。使用 MongoTemplate,您將看到我們對於我們查詢的內容和結果中包含的數據有更精細的控制。

定義數據訪問層介面

為了在數據訪問層提供一個合同,我們將首先定義一個接口,它的工作方式就像我們的 Spring Data 內置方法一樣。

package com.journaldev.bootifulmongodb.dal;

import java.util.List;

import com.journaldev.bootifulmongodb.model.User;

public interface UserDAL {

	List<User> getAllUsers();

	User getUserById(String userId);

	User addNewUser(User user);

	Object getAllUserSettings(String userId);

	String getUserSetting(String userId, String key);

	String addUserSetting(String userId, String key, String value);
}

實現數據訪問層介面

讓我們繼續並定義這些方法。

package com.journaldev.bootifulmongodb.dal;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;

import com.journaldev.bootifulmongodb.model.User;

@Repository
public class UserDALImpl implements UserDAL {

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public List getAllUsers() {
		return mongoTemplate.findAll(User.class);
	}

	@Override
	public User getUserById(String userId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("userId").is(userId));
		return mongoTemplate.findOne(query, User.class);
	}

	@Override
	public User addNewUser(User user) {
		mongoTemplate.save(user);
		// 現在,用戶對象也將包含 ID
		return user;
	}

	@Override
	public Object getAllUserSettings(String userId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("userId").is(userId));
		User user = mongoTemplate.findOne(query, User.class);
		return user != null ? user.getUserSettings() : "User not found.";
	}

	@Override
	public String getUserSetting(String userId, String key) {
		Query query = new Query();
		query.fields().include("userSettings");
		query.addCriteria(Criteria.where("userId").is(userId).andOperator(Criteria.where("userSettings." + key).exists(true)));
		User user = mongoTemplate.findOne(query, User.class);
		return user != null ? user.getUserSettings().get(key) : "Not found.";
	}

	@Override
	public String addUserSetting(String userId, String key, String value) {
		Query query = new Query();
		query.addCriteria(Criteria.where("userId").is(userId));
		User user = mongoTemplate.findOne(query, User.class);
		if (user != null) {
			user.getUserSettings().put(key, value);
			mongoTemplate.save(user);
			return "Key added.";
		} else {
			return "User not found.";
		}
	}
}

上述類中的方法實現使用了 MongoTemplate 依賴項。看看 getUserById(...) 方法如何獲取用戶。我們構建了一個查詢並傳遞了所需的參數。更讓您感興趣的是 getUserSetting 查詢。讓我們了解一下上面發生了什麼:

  • 我們使用標準來構建查詢以檢查相等性。
  • 在提取自數據庫時,include方法將包含結果應包含的字段名。這意味著在這種情況下,將提取userSettings鍵,這將節省不需要擷取的大量數據
  • 同時,我們對用戶和地圖鍵進行了查詢。如果其中任何一個未找到,我們將返回空數據,這意味著未找到所需的鍵。這樣即使未找到所需的鍵,也可以完全避免擷取User對象

Spring Data MongoDB 測試運行

我們只需使用一個命令就可以運行此應用程序:

mvn spring-boot:run

應用程序運行後,我們可以嘗試使用此API保存新用戶:

https://localhost:8102/user/create

由於這將是一個POST請求,我們還將發送JSON數據:

{
  "name" : "Shubham",
  "userSettings" : {
    "bike" : "pulsar"
  }
}

由於我們返回Mongo響應本身,我們將得到類似於:

{
  "userId": "5a5f28cc3178058b0fafe1dd",
  "name": "Shubham",
  "creationDate": 1516165830856,
  "userSettings": {
    "bike" : "pulsar"
  }
}

通過將API用作GET請求,您可以獲取所有用戶:

https://localhost:8102/user/

我們將獲得類似於:

[
  {
    "userId": "5a5f28cc3178058b0fafe1dd",
    "name": "Shubham",
    "creationDate": 1516165830856,
    "userSettings": {
      "bike" : "pulsar"
    }
  }
]

如果您查看上面的UserController類,我們尚未連接MongoTemplate以供使用。下面的代碼片段顯示了使用MongoTemplate讀取用戶設置所需的更改。

//定義數據訪問層對象
private final UserDAL userDAL;

//通過構造函數自動連線初始化DAL對象
public UserController(UserRepository userRepository, UserDAL userDAL) {
	this.userRepository = userRepository;
	this.userDAL = userDAL;
}

//更改方法實現以使用DAL和MongoTemplate
@RequestMapping(value = "/settings/{userId}", method = RequestMethod.GET)
public Object getAllUserSettings(@PathVariable String userId) {
    User user = userRepository.findOne(userId);
    if (user != null) {
        return userDAL.getAllUserSettings(userId);
    } else {
        return "User not found.";
    }
}

//更改方法實現以使用DAL和MongoTemplate
@RequestMapping(value = "/settings/{userId}/{key}", method = RequestMethod.GET)
public String getUserSetting(
        @PathVariable String userId, @PathVariable String key) {
    return userDAL.getUserSetting(userId, key);
}

重新啟動應用程序並運行方案以獲取所有用戶設置和任何特定密鑰。下圖顯示了Postman應用程序的輸出。

MongoTemplate vs MongoRepository

  • MongoTemplate在查詢數據和從數據庫中拉取數據方面提供了更多控制。
  • Spring Data存儲庫為我們提供了一個方便的方式來提取數據。
  • MongoTemplate是數據庫依賴的。這意味著,使用Spring Data存儲庫,您可以通過僅使用不同的Spring Data存儲庫(例如MySQL或Neo4J或其他任何數據庫)輕鬆切換到完全不同的數據庫。MongoTemplate不支持這一點。

Spring Boot MongoDB總結

在這堂課中,我們看了一下 MongoTemplate 如何能夠為我們提供更多對於 Spring Data 倉庫的控制,但是當涉及到更深入的查詢時可能會有些複雜。所以,在開發您的想法時,完全由您決定要選擇什麼。請隨意在下面留下評論。從下面的鏈接下載源代碼。在運行提供的應用程序之前,請確保更改 MongoDB 憑證。

下載 Spring Boot MongoDB 示例項目

Source:
https://www.digitalocean.com/community/tutorials/spring-boot-mongodb