英文:
How to create LinkedList of JPA entities
问题
以下是您提供的内容的翻译部分:
我有一个场景,我需要创建一个实体,该实体引用了前置任务列表和后续任务列表。当收到请求时,我需要创建以下形式的实体:
请求:
{
// 为task2创建请求详细信息
"predecessors": ["task1"],
"successors": ["task3"]
}
我的新实体 "task2" 现在应该在数据库中创建如下:
task1 <- task2 -> task3
task1 -> task2
task2 <- task3
在将任务2保存为前置任务为task1,后续任务为task3时,我还想将任务1的后续任务更新为任务2,将任务3的前置任务更新为任务1。
我在为上述情况设计JPA实体关系方面遇到了困难。
@Entity
@Table(name = "task")
public class Entity {
@ManyToMany
private Set<TaskDatabaseEntity> successors;
@ManyToMany
private Set<TaskDatabaseEntity> predecessors;
}
更新:以下是我尝试保存实体的代码。
TaskDatabaseEntity newTaskEntity = taskEntityFromCreateEvent();
List<TaskDatabaseEntity> taskEntities = List.ofAll(new ArrayList<>());
if (domainEvent.getPredecessors() != null && !domainEvent.getPredecessors().isEmpty()) {
for (TaskEvent event : domainEvent.getPredecessors()) {
TaskDatabaseEntity entity = taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
java.util.Set<TaskDatabaseEntity> suc = entity.getSuccessors() == null ?
new HashSet<>() : entity.getSuccessors();
suc.add(newTaskEntity);
taskEntities.append(entity);
newTaskEntity.getPredecessors().add(entity);
}
}
if (domainEvent.getSuccessors() != null && !domainEvent.getSuccessors().isEmpty()) {
for (TaskEvent event : domainEvent.getSuccessors()) {
taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
TaskDatabaseEntity entity = taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
java.util.Set<TaskDatabaseEntity> pre = entity.getPredecessors() == null ?
new HashSet<>() : entity.getPredecessors();
pre.add(newTaskEntity);
taskEntities.append(entity);
newTaskEntity.getSuccessors().add(entity);
}
}
taskEntities.append(newTaskEntity);
List<TaskDatabaseEntity> savedEntities = List.ofAll(taskEntityRepository.saveAll(taskEntities));
newTaskEntity = savedEntities.filter(task -> task.getObjectId().equals(domainEvent.getEventId())).toList().get(0);
我正在使用 saveAll
一次性更新所有实体,但返回的保存列表为空。我不明白为什么会这样。您对我哪里做错了有什么建议吗?我怀疑我的实体关系可能有问题。
更新 1:我尝试通过 mappedBy
来维护彼此的关系,这样关系会被隐含,我就不需要更新所有实体。
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToMany(mappedBy = "predecessors", fetch = FetchType.LAZY)
private Set<TaskDatabaseEntity> successors;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(schema = "eai", name = "task_ancestors")
private Set<TaskDatabaseEntity> predecessors;
现在我是这样保存它的:
TaskDatabaseEntity newTaskEntity = taskEntityFromCreateEvent();
if (domainEvent.getPredecessors() != null && !domainEvent.getPredecessors().isEmpty()) {
for (TaskEvent event : domainEvent.getPredecessors()) {
TaskDatabaseEntity entity = taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
newTaskEntity.getPredecessors().add(entity);
}
}
newTaskEntity = taskEntityRepository.save(newTaskEntity);
我现在能够保存新的实体及其前置任务,而后续任务可以从表中隐含地获取,如下图所示:【图片链接】。
英文:
I have a scenario where I need to create an entity which has references to list of predecessors and list of successors. when a request is received, I need to create entity like below:
Request:
{
// create request details for task2
"predecessors": ["task1"],
"successors": ["task3"]
}
My new entity "task2" should now be created as below in DB.
task1 <- task2 -> task3
task1 -> task2
task2 <- task3
While saving task2 with previous as task1 and next as task3, I also would like to update task1's next as task2 and task3's previous as task1.
I am struggling to come up with a JPA entity relationship for the above scenario.
@Entity
@Table(name = "task")
public class Entity {
@ManyToMany
private Set<TaskDatabaseEntity> successors;
@ManyToMany
private Set<TaskDatabaseEntity> predecessors;
}
Update: Below is the the code how I am trying to save the entities.
TaskDatabaseEntity newTaskEntity = taskEntityFromCreateEvent();
List<TaskDatabaseEntity> taskEntities = List.ofAll(new ArrayList<>());
if(domainEvent.getPredecessors() != null && !domainEvent.getPredecessors().isEmpty()) {
for(TaskEvent event : domainEvent.getPredecessors()) {
TaskDatabaseEntity entity = taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
java.util.Set<TaskDatabaseEntity> suc = entity.getSuccessors() == null?
new HashSet<>() : entity.getSuccessors();
suc.add(newTaskEntity);
taskEntities.append(entity);
newTaskEntity.getPredecessors().add(entity);
}
}
if(domainEvent.getSuccessors() != null && !domainEvent.getSuccessors().isEmpty()) {
for(TaskEvent event : domainEvent.getSuccessors()) {
taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
TaskDatabaseEntity entity = taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
java.util.Set<TaskDatabaseEntity> pre = entity.getPredecessors() == null?
new HashSet<>() : entity.getPredecessors();
pre.add(newTaskEntity);
taskEntities.append(entity);
newTaskEntity.getSuccessors().add(entity);
}
}
taskEntities.append(newTaskEntity);
List<TaskDatabaseEntity> savedEntities = List.ofAll(taskEntityRepository.saveAll(taskEntities));
newTaskEntity =
savedEntities.filter(task -> task.getObjectId().equals(domainEvent.getEventId())).toList().get(0);
I am updating all the entities together using saveAll
, but the return saved list coming as empty. I do not understand why. Any suggestions on where I am going wrong? I am doubting my entity relationship, may be I have defined relation wrong.
Update 1:
I have tried to maintain the relationship of one another through mappedBy
, that way the relation will be implied and I dont need to update all the entities.
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToMany(mappedBy="predecessors", fetch = FetchType.LAZY)
private Set<TaskDatabaseEntity> successors;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(schema = "eai", name = "task_ancestors")
private Set<TaskDatabaseEntity> predecessors;
Here is how I am now saving it
TaskDatabaseEntity newTaskEntity = taskEntityFromCreateEvent();
if(domainEvent.getPredecessors() != null && !domainEvent.getPredecessors().isEmpty()) {
for(TaskEvent event : domainEvent.getPredecessors()) {
TaskDatabaseEntity entity = taskEntityFromUpdateEvent((TaskUpdate) event, userEntity);
newTaskEntity.getPredecessors().add(entity);
}
}
newTaskEntity = taskEntityRepository.save(newTaskEntity);
I am able to now save the new entity with its predecessors and the successors can be implied from the table as below
答案1
得分: 2
在标题中,您提到了 LinkedList
,但在您的实体中,关系设置为 ManyToMany,这样后继节点和前驱节点就以“平铺”的方式加入到实体中。我根据这种 ManyToMany 的方法准备了我的答案,但同样适用于更像是 LinkedList 实现的 OneToOne 方法。
我认为您可能遗漏了级联操作,而且可能没有正确设置关系的双向。请参考我简化并且“同步”的(您的命名有点令人困惑)示例:
Task(原为实体)
@Entity
@Table(name = "task")
@Getter @Setter
public class Task {
@Id
@GeneratedValue
private Long id;
// 设置持久化操作也会持久化后继节点
@ManyToMany(cascade = CascadeType.PERSIST)
private Set<Task> successors = new HashSet<>();
// 设置持久化操作也会持久化前驱节点
@ManyToMany(cascade = CascadeType.PERSIST)
private Set<Task> predecessors = new HashSet<>();
}
测试
private Task task1 = new Task();
private Task task2 = new Task();
private Task task3 = new Task();
@Resource
private TaskRepository repo;
@Test
void test() {
// 假设历史顺序为 task1 > task2 > task3
// 在持久化之前,您需要处理关系的双向
// 对于两个列表都要处理。
task2.getPredecessors().add(task1);
task1.getSuccessors().add(task2);
task2.getSuccessors().add(task3);
task3.getPredecessors().add(task2);
repo.save(task2);
}
英文:
In title you mention LinkedList
but in your entity the relationship is set ManyToMany so that successors and predecessors an joined to your entity in a "flat" manner. I prepared my answer according to this ManyToMany approach but it is easily applied to OneToOne approach that is more like LinkedList implementation.
I think that you are missing cascade and maybe not correctly setting both sides of relationship. See my simplified and "synchronized" (your naming was a bit confusing) example:
Task (was Entity)
@Entity
@Table(name = "task")
@Getter @Setter
public class Task {
@Id
@GeneratedValue
private Long id;
// Sets the persist operation persist also successors
@ManyToMany(cascade = CascadeType.PERSIST)
private Set<Task> successors = new HashSet<>();
// Sets the persist operation persist also predecessors
@ManyToMany(cascade = CascadeType.PERSIST)
private Set<Task> predecessors = new HashSet<>();
}
Test it
private Task task1 = new Task();
private Task task2 = new Task();
private Task task3 = new Task();
@Resource
private TaskRepository repo;
@Test
void test() {
// assuming history order task1 > task2 > task3
// You need to handle both sides of relationship before persisting
// for both lists.
task2.getPredecessors().add(task1);
task1.getSuccessors().add(task2);
task2.getSuccessors().add(task3);
task3.getPredecessors().add(task2);
repo.save(task2);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论