Spring Boot MongoDB
欢迎使用 Spring Boot MongoDB示例。Spring Boot 是快速启动 Spring 项目的最简单方法,而 MongoDB 是最流行的 NoSQL 数据库。让我们看看如何将 Spring 与 MongoDB 数据库集成。
Spring Boot MongoDB
我们需要以下 API 来使用 Spring Boot 和 MongoDB 数据库。
- Spring 数据 MongoDB
- Spring Boot
我们可以通过两种方法连接到 MongoDB 数据库 -MongoRepository
和MongoTemplate
。我们将尝试确定一个 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 central 的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 为我们提供了常见的功能,我们可以轻松插入并使用它。让我们定义我们的 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 属性来执行此操作。
#Local MongoDB config
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
# App config
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.";
}
}
请注意,在上面的查询中,我们获取了用户对象,然后提取了完整的设置映射(可能包含 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,您将看到我们可以更精细地控制查询的内容以及结果中包含的数据。
定义 DAL 接口
为了在数据库访问层提供契约,我们首先定义一个与 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);
}
实现 DAL 接口
让我们继续并定义这些方法。
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<User> 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);
// Now, user object will contain the ID as well
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 键,这将节省大量不需要的数据
- 此外,我们查询了用户和地图键。如果未找到任何 ID,我们将返回空数据,这意味着未找到所需的键。如果所需的键不存在,这甚至可以避免获取用户对象
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 读取用户设置所需的更改。
//define Data Access Layer object
private final UserDAL userDAL;
//initialize DAL object via constructor autowiring
public UserController(UserRepository userRepository, UserDAL userDAL) {
this.userRepository = userRepository;
this.userDAL = userDAL;
}
//change method implementation to use DAL and hence 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.";
}
}
//change method implementation to use DAL and hence 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 示例项目