Добро пожаловать в пример Spring Boot MongoDB. Spring Boot – самый простой способ быстро создать проект Spring, а MongoDB – самая популярная NoSQL база данных. Давайте посмотрим, как интегрировать Spring с базой данных MongoDB.
Spring Boot MongoDB
Нам нужны следующие API для работы с Spring Boot и базой данных MongoDB.
- Spring Data MongoDB
- Spring Boot
Существует два подхода, через которые мы можем подключиться к базе данных MongoDB – MongoRepository
и MongoTemplate
. Мы попытаемся определить, что одно API предлагает по сравнению с другим, и когда вам следует выбрать один из них для вашего случая использования. Мы воспользуемся инструментом Spring Initializr для быстрой настройки проекта. Итак, приступим.
Настройка проекта Spring Boot MongoDB
Мы воспользуемся инструментом Spring Initializr для быстрой настройки проекта. Мы будем использовать всего две зависимости, как показано ниже: Скачайте проект и разархивируйте его. Затем импортируйте его в вашу любимую среду разработки – 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>
Обязательно используйте стабильную версию для Spring Boot из центрального репозитория Maven.
Класс модели 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;
}
}
API Spring Boot MongoDB
У нас будет следующие функции и взаимодействия с базой данных в нашем приложении.
- Получить всех пользователей
- Получить пользователя по ID
- Получить настройки пользователя
- Получить определенный ключ из карты
- Добавить/обновить настройки пользователя
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 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;
}
}
Мы просто Autowired зависимость интерфейса репозитория, и будем использовать её далее.
Определение API
Для функционала, о котором мы упоминали, мы теперь создадим API и будем использовать зависимость от userRepository, которая внутренне будет использовать API Spring Data MongoRepository. Обратите внимание, что нам не нужно писать какой-либо код взаимодействия с базой данных в интерфейсе, так как 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, когда мы используем его как прямой API.
Добавление новой настройки пользователя
Давайте попробуем добавить некоторые данные к существующему пользователю:
@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.";
}
}
Со всем кодом, который мы написали, ясно, что нам не пришлось писать ни одной строки кода для доступа к базе данных, кроме как определить интерфейс репозитория и провести автопровязку зависимостей. Это предлагает нам простоту API Spring Data MongoRepository
, но у него также есть некоторые недостатки. Мы разберем это, когда также определим версию 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 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);
// Теперь объект пользователя также будет содержать идентификатор
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"
}
}
Поскольку мы возвращаем сам ответ от MongoDB, мы получим что-то вроде:
{
"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 перед запуском предоставленного приложения.
Source:
https://www.digitalocean.com/community/tutorials/spring-boot-mongodb