且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如果父级不存在,弹簧数据保存只会创建级联子级

更新时间:2023-02-05 13:58:05

当你在一个新的 Question 上调用 questionRepo.save() 时,Spring Data 会识别你'重新尝试保存新实体,并在内部调用 EntityManager.persist().

When you call questionRepo.save() on a new Question, Spring Data recognizes that you're trying to save a new entity, and invokes EntityManager.persist() internally.

EntityManager.persist(entity) 使作为参数传递的实体持久.

但是,当您在现有 Question 上调用 questionRepo.save() 时,Spring Data 会在内部调用 EntityManager.merge().

However, when you call questionRepo.save() on an existing Question, Spring Data invokes EntityManager.merge() internally.

EntityManager.merge(entity) 返回实体的永久副本.

问题是你调用 requestConfig.getNewOptions() 之前调用 questionRepo.save().在您描述的第一种情况下并不重要,因为分配给 question 的原始实例(即使用 Question question = new Question(...); 创建的实例)code>),以及使用 .forEach(o -> config.getOptions().add(o)) 行添加到 Option 的子实例,成为持久化,并获得一个自动生成的 id.

The problem is that you call requestConfig.getNewOptions() before calling questionRepo.save(). It doesn't matter in the first case you've described, since the original instance assigned to question (i.e. the one created using Question question = new Question(...);), as well as the child instances added to Option using the line .forEach(o -> config.getOptions().add(o)), become persistent, and obtain an autogenerated id.

但是,在第二种情况下确实很重要,因为新的子实例使用 .forEach(o -> config.getOptions().add(o))不会持久化.相反,只有 questionRepo.save() 返回的 副本 引用的子实体实例(反过来返回 EntityManager.merge() 的结果代码>)是持久的.

However, it does matter in the second case, since the new child instances added to Option using the line .forEach(o -> config.getOptions().add(o)), do not become persistent. Instead, only the child entity instaces referenced by the copy returned by questionRepo.save() (which in turn returns the result of EntityManager.merge()) are persistent.

您应该在调用 questionRepo.save() 之后简单地构造 idMapping 映射 (使用 question.getConfig().getNewOptions()).那应该处理这两种情况.

You should simply construct the idMapping map after calling questionRepo.save() (using question.getConfig().getNewOptions()). That should handle both cases.