#java #spring #spring-boot #hibernate #jpa
Вопрос:
Поэтому для этого задания у меня должно быть 2 микросервиса (служба задач и служба пользователей), каждый из которых имеет свою собственную базу данных. Задача может быть назначена нескольким пользователям, но нескольким пользователям могут быть назначены несколько задач, поэтому это отношение «многие ко многим».
Оба микросервиса являются приложениями для весенней загрузки, использующими режим гибернации, и я изо всех сил пытаюсь установить эту связь между задачей и пользователем внутри службы задач, потому что я не думаю, что хорошая идея копировать модель пользователя, которая уже существует в службе пользователей, в службу задач.
Это назначение предполагает, что идентификаторы пользователей в обеих базах данных согласованы без использования внешних ключей.
Для контекста:
Диаграмма желаемых отношений сущностей, созданная в режиме гибернации:
Task.java [задача-обслуживание]
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
public class Task extends BaseEntity {
private String name, description;
@ManyToOne
private Lane lane;
@OneToMany
private List<TaskUser> users;
}
TaskUser.java [задача-обслуживание]
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
@EqualsAndHashCode
public class TaskUser {
@Id
private Long id;
@Column(name = "task_id")
private Long taskId;
@Column(name = "user_id")
private Long userId;
}
User.java [пользовательское обслуживание]
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class User extends BaseEntity {
@Column(unique = true)
private String username;
}
В настоящее время Hibernate генерирует таблицу task_user и task_users в базе данных службы задач, и я хотел бы иметь только 1 промежуточную таблицу вместо двух.
Вопрос: Как бы я заставил эти отношения «многие ко многим» работать с Hibernate при работе с двумя разными микросервисами?
Комментарии:
1. Какие задачи вам нужно выполнить? Вы можете начать с бизнес-требований, таких как регистрация пользователя, вход в систему, создание задач, распределение задач и т.д. Во всем этом пользовательский модуль не должен зависеть от службы задач. Хотя служба задач может подключаться к пользовательской службе для извлечения пользовательских данных. Пользовательская база данных не будет содержать сведений о задаче . Просто создайте столбец для пользователя в таблице задач в службе задач
2. У задачи может быть несколько пользователей, поэтому столбец в таблице задач не будет работать, я почти уверен. Кстати, вызов службы задач будет выполняться через веб-приложение angular, а не через службу пользователей.
3. Это просто то, как вы воспринимаете подход. Вы можете
allocation-table
использовать с идентификатором alloc иtask-id
как pk(см. Встраиваемые идентификаторы), а затем связать нескольких пользователей(записи) с одним и тем жеtask-id
и новымalloc-id
(автоматическое создание).4. Как бы это выглядело в контексте гибернации при весенней загрузке?
Ответ №1:
Может быть, лучшее отображение спящего режима :
Task.java [задача-обслуживание]
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
public class Task extends BaseEntity {
private String name, description;
@ManyToOne
private Lane lane;
@OneToMany(mappedBy="task")
private List<TaskUser> users;
}
TaskUser.java [задача-обслуживание]
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
@EqualsAndHashCode
public class TaskUser {
@Id
private Long id;
@ManyToOne
@JoinColumn(name="task_id", nullable=false)
private Task task;
@Column(name = "user_id")
private Long userId;
}
Комментарии:
1. Это сработало, спасибо!
Ответ №2:
Вариант использования: назначьте уже существующую задачу уже существующему пользователю. Вы можете назначить нескольким пользователям одновременно 1 одну задачу.
По запросу
/tasks/allocation/new
Тело запроса:
{
"task-id": 12345,
"users": [
{
"username": "user-1",
"user-id": 101
},
{
"username": "user-2",
"user-id": 102
},
{
"username": "user-3",
"user-id": 103
}
]
}
Запрос на публикацию содержит одну задачу и список сведений о пользователе, которые должны быть выделены для этой задачи.
TaskAllocation.java
@Data
public class TaskAllocation{
@jsonProperty("task-id")
private long taskId;
@JsonProperty("users")
private List<Users> userList;
}
Users.java
@Data
public class Users{
@jsonProperty("username")
private String username;
@JsonProperty("user-id")
private Long userId;
}
РестКонтроллер
@PostMapping("/tasks/allocation/new")
public CompletableFuture<ResponseEntity<?>> assignTaskToUsers(@ResponseBody @Valid TaskAllocation taskAllocation){
// service call
}
Внутренняя служба:
- извлеките задачу из базы данных задач(проверьте, существует ли задача)
- При необходимости извлеките сведения о пользователях из службы пользователей(для каждого пользователя), потребуется асинхронный или повторный вызов службы пользователей. Служба задач не содержит сведений о пользователях.
- Для каждого пользователя: 1.Создайте новое распределение
- Установить идентификатор задачи
- Установите идентификатор пользователя или имя пользователя
- Сохранить
Задача уже существует
Таблица Распределение задач
--------------------------------------------------------------
alloc-id(Pk) task-Id(Fk) user-id timetamp
--------------------------------------------------------------
1 12345 101 123123123123
2 12345 102 123123123123
3 12345 103 123123123123
Сущности
Task
и TaskAllocation
имеет отношение 1:n, т. е. task-allocation
таблица состоит из нескольких записей с одним и тем же task-id
.
Task.java
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "sirf_tournament")
public class Task extends Auditable<String> implements Serializable {
@Id
@GeneratedValue
private Long taskId;
private String taskName;
// others
@OneToMany(
fetch = FetchType.LAZY,
mappedBy = "task",
cascade = CascadeType.ALL,
orphanRemoval = true)
private Collection<TaskAllocation> taskAllocation = new HashSet<>();
}
TaskAllocation.java
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "sirf_tournament")
public class TaskAllocation extends Auditable<String> implements Serializable {
@Id
@GeneratedValue
private Long allocId;
private Long userId;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "taskId")
private Task task;
// others
}
User
таблица и другие связанные с ней объекты здесь не упоминаются. Служба задач не располагает информацией о пользователях.
Было бы хорошо, если бы вы проверили всех пользователей(все идентификаторы могут быть проверены одним вызовом, возвращают недопустимые идентификаторы из службы пользователей) и идентификаторы задач, прежде чем сохранять их в таблице.
Комментарии:
1. Однако я не вижу никаких аннотаций Hibernate?
2. Сущности все просты, как и в любых других случаях. Позвольте мне обновить ответ.