#java #mongodb #postgresql #spring-boot
#java #mongodb #postgresql #spring-boot
Вопрос:
Я создал службу управления пользователями, в которой я использую MongoDB (spring data). У меня есть две модели User и Role.
package com.userservice.usermanagement.models;
import java.util.HashSet;
import java.util.Set;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "user_data")
public class User {
/**
* User model
*/
@Id
private String id;
private String username;
private String email;
private String password;
private String customername;
private String customerid;
private String description;
public String getCustomerid() {
return customerid;
}
public void setCustomerid(String customerid) {
this.customerid = customerid;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCustomername() {
return customername;
}
public void setCustomername(String customername) {
this.customername = customername;
}
@DBRef
private Set<Role> roles = new HashSet<>();
public User() {
}
public User(String username, String email, String customername,String customerid,String description, String password) {
this.username = username;
this.email = email;
this.customername = customername;
this.customerid = customerid;
this.description = description;
this.password = password;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Ролевая модель —
package com.userservice.usermanagement.models;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "roles")
public class Role {
/**
* Model for role with all the attributes
*/
@Id
private String id;
private URole name;
public Role() {
}
public Role(URole name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public URole getName() {
return name;
}
public void setName(URole name) {
this.name = name;
}
}
и перечислитель ролей-
package com.userservice.usermanagement.models;
public enum URole {
ROLE_USER,
ROLE_ADMIN
}
У пользователя есть атрибут роли, который у меня есть @Dbref для коллекции ролей. Моя проблема в том, что я хочу иметь возможность использовать PostgreSQL и MongoDB в одном приложении для этих моделей. Я реализовал это для MongoDB, но я не уверен, как сделать это для PostgreSQL в том же приложении в качестве опции. Один из способов, я думаю, состоит в том, чтобы иметь пользователя интерфейса и роль и создать два разных класса для модели User_mongo и сущности User_postgre (аналогично для роли). Я застрял здесь, и я попытался провести определенные исследования, но большую часть времени я нахожу учебные пособия, в которых есть отдельные базы данных одного и того же типа (обе базы данных PostgreSQL). Приветствуется любое направление. PS Я новичок в spring boot и Java.
Мой контроллер AddUser, который на данный момент использует Mongorepository
@PostMapping("/adduser")
// @PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
/*
* This controller Creates new user based on all the entities for the user
*
*/
if (userRepository.existsByUsername(signUpRequest.getUsername())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Username is already taken!"));
}
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Email is already in use!"));
}
// Create new user's account
User user = new User(signUpRequest.getUsername(),
signUpRequest.getEmail(),
signUpRequest.getCustomername(),
signUpRequest.getCustomerid(),
signUpRequest.getDescription(),
encoder.encode(signUpRequest.getPassword()));
Set<String> strRoles = signUpRequest.getRoles();
Set<Role> roles = new HashSet<>();
if (strRoles == null) {
Role userRole = roleRepository.findByName(URole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
} else {
strRoles.forEach(role -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(URole.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(adminRole);
break;
default:
Role userRole = roleRepository.findByName(URole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
}
});
}
user.setRoles(roles);
userRepository.save(user);
return ResponseEntity.ok(new MessageResponse("User Added successfully!"));
}
```
Комментарии:
1. Зачем вам нужна база данных 2 для ваших моделей. Я имею в виду, что на земле может быть причиной этого? Вы можете сохранить все свойства, связанные с БД, в своем приложении. файл yaml. Прокомментируйте тот, который вам не нужен. И когда вам это понадобится, раскомментируйте его и закомментируйте другие свойства БД. На самом деле это делается через config server. Где вы храните разные наборы свойств для разных сред, таких как Production, Dev, QA и т.д…. В какой бы среде вы ни нуждались, просто добавьте значение в spring.profile. Spring boot считает значение с сервера конфигурации.
2. Правильно, я понимаю, так что это требование от разных клиентов, в которых некоторым из них нужен Mongo, а другим нужен PostgreSQL. Проблема с вашим приложением заключается в том, что на основе этих моделей я буду правильно создавать репозитории? Например, служба реализации UserService использует Userepository, построенный на модели пользователя mongo, для извлечения данных из БД. Я не могу продолжать комментировать свой код и там. Должно быть лучшее решение. В этой статье кое-что выглядит актуальным, но не уверен. dzone.com/articles/how-springboot-autoconfiguration-magic-works
3. Да .. это то, что я вам говорил. Используйте spring.profiles.active, чтобы указать на БД в соответствии с вашими требованиями. Как правило, в Dev env и prod env могут быть разные базы данных. По этой причине вы используете профили. но в том же приложении spring boot, если разные модели используют разные базы данных, вам необходимо настроить класс для чтения разных свойств источника данных для разных БД и соответствующим образом инициализировать ваш репозиторий. @Conditional также можно использовать.
4. Отлично, похоже, я в правильном направлении, но у меня все еще есть блок в моем понимании. Я отредактировал свой вопрос с помощью контроллера «addUser», который я использую. Как вы можете видеть, у меня там есть пользовательское хранилище. Мой вопрос в том, когда у меня есть база данных PostGres, о которой идет речь, тогда мне нужно будет создать репозиторий для этого и в этом сценарии, как изменится этот код? Извините, если это должен быть вопрос новичка. но я зациклен на этой части
Ответ №1:
Я бы использовал аннотацию @ConditonalOnProperty здесь для двух конфигураций (одна для Mongo и одна для PostgerSql) и добавил enabled config-property во время выполнения (для конфигурации, которую вы хотите загрузить)
Вот упрощенный пример.
public static void main(String[] args) {
SpringApplication application = new SpringApplication(DemoApplication.class);
Properties properties = new Properties();
properties.put("databaseFoo.enabled", "true");
application.setDefaultProperties(properties);
application.run(args);
}
then on the config needed when run time is databaseFoo you can annotate the bean as such
@ConditionalOnProperty(
value="databaseFoo.enabled",
havingValue = "true")
public class DatabaseFooConfig {
Then the other bean could have the following conditional properties
@ConditionalOnProperty(
value="databaseBar.nabled",
havingValue = "false",
matchIfMissing= true)
public class DataBaseBarConfig {
Комментарии:
1. Да, так что же именно происходит в DatabaseBarConfig?. Как и в операциях crud контроллера, я использовал репозиторий mongo вручную, как я могу сделать это необязательным?
2. В DatabaseBarConfig вы создаете необходимые вам компоненты конфигурации. Например, один компонент конфигурации для предоставления источника данных, другой для управления транзакциями .. и т.д. Компоненты будут созданы «зарегистрированными в springContext», если для флага установлено значение true. Иначе они не будут созданы,