Jpa spring数据保存仅在父级不存在时创建级联子级
我有以下实体:Jpa spring数据保存仅在父级不存在时创建级联子级,jpa,spring-data,Jpa,Spring Data,我有以下实体:Question有OneToOneConfig。而Config有许多选项。全部配置为级联。全部配置为级联(s.附录) 基于RequestDTO(requestConfig),我为一个新问题或一个现有问题创建了选项实体,其id=null 在这两种情况下,我都希望访问新选项的生成ID。但是,它确实适用于新问题,但不适用于现有问题: 新问题(确定) 实体:问题 @Entity public class Question { @OneToOne(fetch = FetchType.
Question
有OneToOneConfig
。而Config
有许多选项。全部配置为级联。全部配置为级联(s.附录)
基于RequestDTO
(requestConfig
),我为一个新问题或一个现有问题创建了选项
实体,其id=null
在这两种情况下,我都希望访问新选项的生成ID
。但是,它确实适用于新问题,但不适用于现有问题:
新问题(确定)
实体:问题
@Entity
public class Question {
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "config_id", nullable = false)
private Config config;
// ...
}
@Entity
public class Option {
@ManyToOne
@JoinColumn(name = "config_id", nullable = false)
private Config config;
public Option(Long id, Config config) {
super();
this.id = id;
this.config = config;
}
// ...
}
实体:配置
@Entity
public class Config {
@OneToOne(mappedBy = "config")
@JoinColumn(name = "question_id", nullable = true)
private Question question;
@OneToMany(mappedBy = "config", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Option> options = new ArrayList<>();
// ...
}
当您对一个新的问题调用questionRepo.save()
时,Spring数据会识别您正试图保存一个新实体,并在内部调用EntityManager.persist()
EntityManager.persist(entity)
使作为参数传递的实体持久化
但是,当您对现有的问题调用questionRepo.save()
时,Spring数据会在内部调用EntityManager.merge()
EntityManager.merge(entity)
返回该实体的持久副本
问题是在调用questionRepo.save()
之前调用了requestConfig.getNewOptions()
。在您描述的第一种情况下,这并不重要,因为原始实例分配给question
(即使用question question=new question(…);
创建的实例),以及使用行添加到选项的子实例,变得持久化,并获取自动生成的id
但是,在第二种情况下,并不重要,因为使用行将新的子实例添加到选项
。forEach(o->config.getOptions().add(o))
,不会持久化。相反,只有由questionRepo.save()
返回的副本引用的子实体instance(该副本反过来返回EntityManager.merge()
的结果)是持久的
调用questionRepo.save()
(使用question.getConfig().getNewOptions()
)后,您只需构造idMapping
映射即可。这两种情况都可以处理
我检查了数据库,它们被插入了
entityManager只返回当前实体的新id,而不是通过cascade保存的相关实体。保存问题后,请尝试通过问题id再次查找。谢谢您的尝试!虽然您的解释更清楚地说明了问题所在,但建议的解决方案不起作用:配置的newOptions
字段是在save(…)
之前构建的(调用requestDTO.getConfig(…)
并且它不能在保存
之后执行,因为保存操作的一部分应该存储新选项。新选项
字段确实包含ID为空的选项
对象。
@Entity
public class Question {
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "config_id", nullable = false)
private Config config;
// ...
}
@Entity
public class Config {
@OneToOne(mappedBy = "config")
@JoinColumn(name = "question_id", nullable = true)
private Question question;
@OneToMany(mappedBy = "config", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Option> options = new ArrayList<>();
// ...
}
@Entity
public class Option {
@ManyToOne
@JoinColumn(name = "config_id", nullable = false)
private Config config;
public Option(Long id, Config config) {
super();
this.id = id;
this.config = config;
}
// ...
}