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 获取用户
  • 获取用户设置
  • 从 Map 中获取特定键
  • 添加/更新用户设置

Spring Data MongoDB – MongoRepository

现在我们将使用Spring Data MongoDB存储库来访问我们的数据。Spring Data MongoRepository为我们提供了常用功能,我们可以轻松地插入并使用它。让我们定义我们的存储库接口。

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控制器

最后让我们开始创建我们的控制器类。

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.";
	}
}

请注意,在上面的查询中,我们获取了用户对象,然后提取了完整的设置映射(可能包含数千个对象),最后获取了我们自己的值。这是当我们直接使用 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键,这将节省不需要获取的大量数据。
  • 此外,我们查询了用户和地图键。如果其中任何一个未找到,我们将返回空数据,这意味着未找到所需的键。这甚至可以避免在未找到所需键的情况下完全获取用户对象。

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