【问题标题】:JPA does not insert new childs from one to many relationship when we use merge当我们使用合并时,JPA 不会从一对多关系中插入新的孩子
【发布时间】:2016-03-03 20:17:42
【问题描述】:

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

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,但仍然无法解决我的问题

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

我可以用我想要的任何孩子创建一个 Parent,并更新这些孩子,但不能添加新的孩子。

例子:

@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() 之前的值不为空。我正在使用休眠提供程序。我可以在列表中插入带有我想要的任何 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;
}

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

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

【问题讨论】:

  • 你在moreOneChild中设置了父级吗?你能举一个更简单的例子吗?
  • 抱歉,代码已编辑。看起来问题与具有复合主键有关。我还在研究。
  • 我可以让你的保存序列正常工作,所以这没有什么问题。你需要提出一个可重复的问题。如果您有一个复合主键并且您遇到键违规,那么这需要成为您问题的基础
  • 知道了,谢谢提示,这是我的 seconf 问题,下次我会尝试改进我的问题。
  • 当您尝试在列表中再插入一个 SerieExercise 时,代码在哪里?

标签: java hibernate jpa


【解决方案1】:

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

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

我的意思是,通常在@ManyToOne 关系的所有者方面,您必须使用@JoinColumn。也许是无礼但值得一提。

另外,我们希望看到完整的代码和完整的堆栈跟踪,尤其是子 ID 映射(复合 id 可能是或不是原因,但请提供完整代码)。在 ID 再生方面,有时底层数据库和 JPA 实现库可能很重要。您使用的是 EclipseLink、Toplink 还是其他?

【讨论】:

  • 是的,问题与复合键有关。我已将复合键更改为自动生成的 ID,它解决了问题。非常感谢。
  • 我用我的真实代码和错误编辑了帖子,你知道我该怎么做才能使它与复合键一起工作吗?我的映射有问题吗?我可以正确持久化并编辑持久化的值,但不能添加新的“SerieExercise”。
  • 如果您仍想添加 CompositeID,我认为您应该发布您的 CompositeID 代码、要映射的字段等。但是如果你对 Simple ID 满意,那就没问题了……其实我通常不使用复合 ID,而且我没有看到很多真正需要的情况。
【解决方案2】:

这行代码在我看来是错误的:

parent.addChildren(moreOneChild);

我原以为应该是这样的:

List<Child> children = parent.getChildren();
children.add(moreOneChild);
entityManager.merge(parent);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 2021-01-07
    相关资源
    最近更新 更多