【问题标题】:Issue while updating @OneToMany collection更新 @OneToMany 集合时出现问题
【发布时间】:2012-05-16 11:42:44
【问题描述】:

我被困在试图更新@OneToMany 映射的地方。

问题: 我有 2 个实体:标准和任务。一个条件可以包含多个任务。

class Criteria {
    @OneToMany(mappedBy = "criteria", cascade = { CascadeType.PERSIST,
    CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)
    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE,
               org.hibernate.annotations.CascadeType.ALL,
               org.hibernate.annotations.CascadeType.MERGE,
               org.hibernate.annotations.CascadeType.PERSIST })
     private Set<Task> tasks;
}

class Task {
    @ManyToOne
    @JoinColumn(name = "CRITERIA_ID", nullable=false)
    private Criteria criteria;
}

我正在尝试使用一组新任务更新现有标准。这需要删除所有现有任务并添加新任务。 这是我的做法:

criteriaDao.persist(criteria);
Set<Task> existingTasks=criteria.getTasks();
if(existingTasks != null) {
    for (Task task : existingTasks) {
        task.setCriteria(null);
    }
    criteria.setTasks(tasks);
    //more code which sets criteria for each task - this works if i try to save new criteria with new tasks
}

Hibernate 抛出异常:

Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint (CCA_DEV_5.TASK__UN) violated

抛出此异常是因为它没有删除现有任务。

如果我只删除所有任务,它可以完美运行并使用以下代码删除给定条件的所有任务:

criteriaDao.persist(criteria);
Set<Task> existingTasks=criteria.getTasks();
if(existingTasks != null) {
    for (Task task : existingTasks) {
    task.setCriteria(null);
}
}

在添加新任务和更多内容后,我尝试了所有使用合并的选项,但似乎没有任何效果。我被严重困在这里,肯定错过了 Hibernate 中一些非常基本的东西。

提前致谢!

【问题讨论】:

    标签: hibernate jpa jpa-2.0 hibernate-mapping hibernate-onetomany


    【解决方案1】:

    在您的Task 类中,您根本不应该引用Criteria。只需将其连同其注释一起删除即可。

    然后,不要设置Task引用的Criteria,因为这个引用不再存在,只需使用criteria.setTasks(newTasks)并保存criteria即可。


    让我解释一下。 CriteriaTask 之间的关系显然是 Criteria 1 --- n Tasks - 1 到 n。现在,您可以调用one-to-many 关系,也可以调用它many-to-one,这取决于您的观点。从Criteria 的角度来看,它是one-to-many,而从Task 的角度来看 - 它是many-to-one。一般来说,从这些观点中选择一个坚持下去是明智且更直观的。选择一个观点,定义“控制”关系的实体,通过该实体应该应用任何修改。

    在您的情况下,如果您将Criteria 视为包含拥有一组Tasks - 您会将关系视为one-to-many .确定之后,就不需要CriteriaTaskjava类引用了。您仅使用 Criteria API 来控制关系(但是,在 DB 中为 Task 创建的表确实有一个引用其包含 Criteria 的列)。

    【讨论】:

    • 嗯...在我看来,多对一应该与一对多一起工作,我没有看到任何问题。 JPA 也支持逆映射。我通过在使用新集合设置集合之前添加以下行来解决此问题 - for (Task task : existingTasks) { task.setCriteria(null); } => session.flush();标准.setTasks(任务);这确保删除语句在插入之前执行。
    • @RakeshSinha 很高兴你解决了这个问题。但是,我建议您阅读this short parent-child hibernate docs example,它解释了如何在one-to-many 关系中使用inverse
    • 谢谢你,我以前看过这个文件,也用过。你认为还有另一种方法可以实现我正在做的事情吗?显式调用 flush() 有效,但这会导致实体管理器将所有查询刷新到 Db。有没有更好的方法来更新集合?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多