【问题标题】:JPA one way cascade operationsJPA 单向级联操作
【发布时间】:2014-07-22 11:06:29
【问题描述】:

我有以下 JPA 2.0 模型:

@Entity
public class Company {

  @OneToMany(mappedBy="company", targetEntity = Department.class, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    private List<Department> departments;

...
}

@Entity
public class Department {
    @ManyToOne
    @JoinColumn(name="company_id")
    private Company company;

...
}

当我尝试删除公司时,一切都很好 - 所有部门都被删除了。但是当我尝试删除部门时,它会引发以下异常: 引起:javax.persistence.EntityNotFoundException:已删除的实体传递给持久化:[my.model.Department#]

是否可以这样配置,当我删除部门时,公司没有任何反应?

@ManyToOne(cascade=CascadeType.REFRESH

关于部门模型并不能解决问题。

【问题讨论】:

    标签: java hibernate jpa jpa-2.0


    【解决方案1】:

    也许您没有从您的Company 实例中的private List&lt;Department&gt; departments; 中删除引用的Department,因此仍引用了已删除的实例。

    从列表中删除已删除的部门,它应该可以工作。

    【讨论】:

    • 我无法从部门列表中删除它,因为该属性未初始化(FetchType 设置为 LAZY,我没有手动获取部门集合)。
    • 我不确定如果没有加载部门实例如何传递给persist。您能否在加载数据的位置添加代码并删除部门?您是否尝试过以编程方式触发加载或使用 fetch join 来解决此问题?
    • 在删除之前,我再次获取了部门,做了department.getCompany().getDepartments().remove(department),然后删除了部门,一切正常。我仍然不知道为什么它在未初始化时试图从 Company 保存部门集合 - 类型是 PersistenceBag。
    【解决方案2】:

    如果您在Company 中添加孤儿删除:

    (JPA 2.0 方式)

      @OneToMany(mappedBy="company", 
                 targetEntity = Department.class,
                 fetch=FetchType.LAZY, 
                 cascade=CascadeType.ALL,
                 orphanRemoval=true)
      private List<Department> departments;
    

    (休眠方式)

      @OneToMany(mappedBy="company", 
                 targetEntity = Department.class,
                 fetch=FetchType.LAZY, 
                 cascade=CascadeType.ALL)
      @Cascade({ org.hibernate.annotations.CascadeType.ALL,
                 org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
      private List<Department> departments;
    

    您可以通过以下方式删除部门:

    company.getDepartments().remove(department);
    

    然后存储Company(或在提交事务时)(假设Department 只能由一个Company 拥有。(无需告诉EntityManager 删除@987654329 @..)

    【讨论】:

    • 好的,但是如果“company”表没有变化,我为什么要保存Company?我想删除部门。
    • 您现在正在使用JPA,您不必担心表操作。由 JPA 提供者来创建必要的查询,如果没有要更新的内容,它可能不会运行查询。从数据库的角度考虑手头的问题时,可能会得出这样的结论:该操作是“删除部门”,但这仅仅是因为这是您在数据库中解决问题的方式。你真正想要实现的是“这个部门不再作为这家公司的一部分存在”(因为公司拥有它的部门。)
    • 一般来说,当你在实体之间有关联时,如果你可以说一方“拥有”另一方(“让这个实体没有与另一个实体的连接有意义吗?” ),那么在拥有方的所有操作都应该通过持久化拥有方来完成。
    • 好的,我知道这种方法可以更轻松地实现业务标准。但是假设公司有 100 万个部门,那么我需要将它们加载到内存中以仅删除一个条目 - 这就是问题所在。
    • 我通常使用 JPA 的方式是首先尝试以 JPA 方式进行,如果结果无法扩展,我将再进行一轮并尝试加快速度。在这种情况下,如果您发现通过 delete-orphan 删除太慢/消耗资源,则直接通过 EntityManager 将其删除(尽管这会破坏部门归公司所有的事实)。此外,将内容加载到内存中并不是一件坏事,在程序执行期间,有问题的公司很可能会被用于某些事情,然后会快得多,因为公司已经在内存中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多