gpt4 book ai didi

java - 当我们使用合并时,JPA 不会从一对多关系中插入新的 child

转载 作者:行者123 更新时间:2023-12-05 07:50:50 24 4
gpt4 key购买 nike

我的问题与以下问题非常相似:

JPA: How do I add new Items to a List with a OneToMany annotation

Why merging is not cascaded on a one to many relationship

JPA with JTA: Persist entity and merge cascaded child entities

我也看了Wikibooks但仍然无法解决我的问题

所以,我的问题是我有一个带有子类的父类,当我添加一个新的子类并使用 entityManager.merge(parent) 更新新的子类时,没有插入并且我得到一个空主键错误。

我可以为任何我想要的 child 创建父级,并更新这些 child ,但不能添加新的 child 。

例子:

@Entity
public class Parent {
private String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
private List<Child> children;
}
@Entity
public class Child {
private String name;
@ManyToOne
private Parent parent;
}

如果我创建一个带有一些子项的父项,它就可以正常工作。如果我更新子项的属性,它工作正常,如果我向父项添加一个新的子项,它就不起作用。

public void foo(){

Parent parent = new Parent();
List<Child> children = new ArrayList<Child>();
children.add(new Child());
children.add(new Child());
children.add(new Child());
parent.setChildren(children);
//it works
entityManager.persist(parent);

//and lets say that I have updated some attributes
changeAttributesValues(parent);
changeAttributesValues(children);
//it still working and the values are updated properly
entityManager.merge(parent);

//but if I add some child
List<Child> children = parent.getChildren();
children.add(moreOneChild);
parent.setChildren(children);
entityManager.merge(parent);
//here I got an error saying that jpa cannot insert my attribute because my PK is null
}

注意:我的 PK 是一个复合键(假设在这个例子中它是 idFromParent + idCompany)

提前致谢。

编辑

我解决了删除复合键并添加自动生成的 ID 的问题。我正在发布我的真实代码以及我为使其工作所做的工作。使用此代码,

@Entity
public class Serie implements Serializable{

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SERIE_ID_SEQ")
@SequenceGenerator(name = "SERIE_ID_SEQ", sequenceName = "real.serie_id_seq")
@Column(name = "idserie")
private Long id;

@Basic
@Column(name = "nmserie")
private String nmSerie;

@OneToMany(mappedBy = "serie", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
private List<SerieExercise> serieExercises;

@ManyToOne
@JoinColumn(name = "idtrainning")
private Trainning Trainning;
}

@Entity
public class SerieExercise implements Serializable{

@Basic
@Column(name = "nrrepetition")
private int nrRepetition;

@Column(name = "tminterval")
@Temporal(TemporalType.TIMESTAMP)
private Date tmInterval;

@Id
@Basic
@Column(name = "nrorder")
private Integer nrOrder;

@Id
@ManyToOne
@JoinColumn(name = "idexercise")
private Exercise exercise;

@Id
@ManyToOne
@JoinColumn(name = "idserie")
private Serie serie;
}

使用此代码,当我尝试在我的列表中再插入一个 SerieExercise 时出现此错误:

Caused by: org.postgresql.util.PSQLException: ERRO: ERROR: null value in column "nrorder" violates not-null constraint
Detail: Failing row contains(null, 10, null, null, null).
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:366)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
... 132 more

我进行了调试,调用 entityManager.merge() 之前的值不为空。我正在使用 hibernate 提供程序。我能够在我的列表中插入一个包含我想要的任何 SerieExercise 的 Serie,并且能够更新值,但无法在我的列表中添加一个新的 SerieExercise。

为了修复,我做了以下更改:

@Entity
public class SerieExercise implements Serializable{

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SER_EXER_ID_SEQ")
@SequenceGenerator(name = "SER_EXER_ID_SEQ", sequenceName = "realvida.ser_exer_id_seq")
@Column(name = "idserieexercicio")
private Long id;

@Basic
@Column(name = "nrrepetition")
private int nrRepetition;

@Column(name = "tminterval")
@Temporal(TemporalType.TIMESTAMP)
private Date tmInterval;

//@Id
@Basic
@Column(name = "nrorder")
private Integer nrOrder;

//@Id
@ManyToOne
@JoinColumn(name = "idexercise")
private Exercise exercise;

//@Id
@ManyToOne
@JoinColumn(name = "idserie")
private Serie serie;
}

有人知道为什么会这样吗?我可以使用复合键完成这项工作吗?

如果您需要更多信息,请告诉我。

最佳答案

我认为您在子端的映射在我看来是错误的。您必须像这样维护这种@ManyToOne 关系:

@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinColumn(name="idParent", nullable=false)
private Parent parent;

我的意思是,通常在 @ManyToOne 关系的所有者端,您必须使用 @JoinColumn。可能不恰当但值得一提。

此外,我们希望看到完整的代码和完整的堆栈跟踪,尤其是子 ID 映射(复合 ID 可能是或不是原因,但请查看完整代码)。当涉及到 ID 重新生成时,有时底层数据库和 JPA 实现库可能很重要。您使用的是 EclipseLink、Toplink 还是其他软件?

关于java - 当我们使用合并时,JPA 不会从一对多关系中插入新的 child ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35782167/

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