gpt4 book ai didi

java - Spring-Data-Jpa 在持久化后清除链接实体的所有参数

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:00:53 27 4
gpt4 key购买 nike

我正在尝试使用 JPA(带有 Hibernate)来保存 2 个实体。 Spring Data 正在提供接口(interface),但我认为这在这里并不重要。

我有一个名为“模型”的主要实体。该模型链接了许多“参数”实体。我正在编写一种方法来保存模型及其参数。

这是方法:

  private void cascadeSave(Model model) {

modelRepository.save(model);

for (ParameterValue value : model.getParameterValues()) {
parameterValueRepository.save(value);
}
}

问题是:

当我加载一个之前已经存在的模型时,向它添加一些新参数,然后调用这个方法来保存它们,但奇怪的事情发生了:

在第一次保存 (modelRepository.save) 之前,这是调试时模型数据的样子:

enter image description here

模型有2个参数,有填充值(name和model都填)。

现在,在我的方法中第一次保存模型后,发生了这种情况。请注意,对象引用是不同的,因此 Hibernate 一定做了一些神奇的事情并重新创建了值而不是让它们单独存在:

enter image description here

由于某些原因,hibernate 清除了集合中参数的所有属性。

现在,当在以下代码中保存新参数时,由于非空约束等原因,它会失败。

我的问题:为什么 hibernate 会清除所有字段?

这里是相关的映射:

参数值

@Entity
@Table(name = "tbl_parameter_value")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "PARAMETER_TYPE")
public abstract class ParameterValue extends AbstractBaseObject {

@Column(nullable = false)
@NotBlank
private String name;
private String stringValue;
private Double doubleValue;
private Integer intValue;
private Boolean booleanValue;
@Enumerated(EnumType.STRING)
private ModelType modelParameterType;
@Column(precision = 7, scale = 6)
private BigDecimal bigDecimalValue;
@Lob
private byte[] blobValue;

ParameterValue() {
}

ParameterValue(String name) {
this.name = name;
}

模型参数值

@Entity
@DiscriminatorValue(value = "MODEL")
public class ModelParameterValue extends ParameterValue {

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "model_id", foreignKey = @ForeignKey(name = "FK_VALUE_MODEL"))
private Model model;

ModelParameterValue() {
super();
}

ModelParameterValue(String name) {
super(name);
}

模型

@Entity
@Table(name = "tbl_model")
public class Model extends AbstractBaseObject implements Auditable {

@OneToMany(fetch = FetchType.LAZY, mappedBy = "model")
private Set<ModelParameterValue> parameterValues = new HashSet<>();

编辑

我能够用一个最小的例子重现这个。如果您替换 spring data 所做的一切,这就是幕后发生的事情(em 是一个 JPA EntityManager):

public Model simpleTest() {

Model model = new Model("My Test Model");
em.persist(model);

model.addParameter(new Parameter("Param 1"));
em.merge(model);

for (Parameter child : model.getParameters()) {
em.persist(child);
}

return model;
}

执行合并时,参数的所有属性都设置为空。它们实际上只是被全新的参数所取代。

最佳答案

我猜你正在使用 Spring Data Jpa 作为你的 modelRepository。这表明以下后果。

Spring Repository Save

S save(S entity)

Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.

所以这是您遇到的正常行为。

代码应更改为:

model = modelRepository.save(model);

for (ParameterValue value : model.getParameterValues()) {
parameterValueRepository.save(value);
}

编辑:

我认为你的保存功能在意义上是错误的,你是倒退的。您可以在您的关系上使用 CascadeType,或者您必须先保存 child 。

级联

Cascade 的工作原理是“如果你保存 Parent,保存 Children,如果你更新 Parent,更新 Children ...”

所以我们可以像这样在你的关系上放置级联:

@Entity
@Table(name = "tbl_model")
public class Model extends AbstractBaseObject implements Auditable {

@OneToMany(fetch = FetchType.LAZY, mappedBy = "model", cascade = CascadeType.ALL)
private Set<ModelParameterValue> parameterValues = new HashSet<>();

然后只这样保存

  private void cascadeSave(Model model) {

modelRepository.save(model);
//ParamValues will be saved/updated automaticlly if your model has changed

}

自下而上保存

第二种选择是先保存参数,然后用它们建模。

  private void cascadeSave(Model model) {

model.setParameterValues(
model.getParameterValues().stream()
.map(param -> parameterValueRepository.save(param))
.collect(Collectors.toSet())
);
modelRepository.save(model);
}

我没有在我的编译器中检查第二个代码,但我的想法是先保存子项 (ParamValues),将其放入模型中,然后保存模型:)

关于java - Spring-Data-Jpa 在持久化后清除链接实体的所有参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52831899/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com