代码之家  ›  专栏  ›  技术社区  ›  Lyle

删除包含@collectionofelements的JPA实体将引发ConstraintVolationException

  •  2
  • Lyle  · 技术社区  · 14 年前

    我正在尝试删除包含整数列表的实体,并且由于生成的表中用于保存整数的外键,我得到了ConstraintIOlationExceptions。似乎删除没有层叠到映射的集合。

    我做了相当多的搜索,但是我所看到的关于如何实现这一点的所有示例都引用了可以注释的其他实体的映射集合;这里我只是存储一个整数列表。以下是我正在存储的类的相关摘录:

    @Entity
    @Table(name="CHANGE_IDS")
    @GenericGenerator(
            name = "CHANGE_ID_GEN",
            strategy =  "org.hibernate.id.enhanced.SequenceStyleGenerator",
            parameters = {
                    @Parameter(name="sequence_name", value="course_changes_seq"),
                    @Parameter(name="increment_size", value="5000"),
                    @Parameter(name=" optimizer", value="pooled")
                         }
        )
    @NamedQueries ({
        @NamedQuery(
            name="Changes.getByStatus",
            query=  "SELECT c " +
                    "FROM DChanges c " +
                    "WHERE c.status = :status "),
        @NamedQuery(
                name="Changes.deleteByStatus",
                query=  "DELETE " +
                        "FROM Changes c " +
                        "WHERE c.status = :status ")
    })
    public class Changes {
        @Id
        @GeneratedValue(generator="CHANGE_ID_GEN")
        @Column(name = "ID")
        private final long id;
    
        @Enumerated(EnumType.STRING)
        @Column(name = "STATUS", length = 20, nullable = false)
        private final Status status;
    
        @Column(name="DOC_ID")
        @org.hibernate.annotations.CollectionOfElements
        @org.hibernate.annotations.IndexColumn(name="DOC_ID_ORDER")
        private List<Integer> docIds;
    }
    

    我正在使用@namedquery删除changes对象:

    final Query deleteQuery = this.entityManager.createNamedQuery("Changes.deleteByStatus");
    deleteQuery.setParameter("status", Status.POST_FLIP);
    final int deleted = deleteQuery.executeUpdate();
    this.logger.info("Deleted " + deleted + " POST_FLIP Changes");
    
    2 回复  |  直到 14 年前
        1
  •  2
  •   Pascal Thivent    14 年前

    HQL删除不会层叠到相关 实体 根据JPA规范(尽管有些用户希望使用中报告的扩展行为 HHH-695 )根据JPA 1.0规范:

    4.10批量更新和删除操作

    (…)

    删除操作仅适用于 指定类的实体和 它的子类。它不会级联到 相关实体。

    (…)

    所以在使用批量删除时,您可以自己使用。

    但是,在特定情况下, CollectionOfElements 它们不是实体(而且由于无法批量删除集合的表),因此我希望以下内容可以工作:

    @Column(name="DOC_ID")
    @org.hibernate.annotations.CollectionOfElements
    @org.hibernate.annotations.IndexColumn(name="DOC_ID_ORDER")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private List<Integer> docIds;
    

    但不幸的是,事实并非如此, SessionFactory 抱怨:

    org.hibernate.MappingException: only inverse one-to-many associations may use on-delete="cascade": com.stackoverflow.q3049451.Changes.docIds
    

    根据 this thread ,这听起来像一个bug…

    因此,这就为您提供了实现的解决方案:执行选择、循环和移除实体。

        2
  •  0
  •   Lyle    14 年前

    经过多次试验,我发现使用 更改.deletebystatus 问题中显示的命名查询不会导致删除被级联到集合表,无论我尝试了哪种注释组合。

    最终我得到了所有匹配的实体 更改.getbystatus 命名查询,然后通过实体管理器删除它们,这似乎可以正确处理层叠。

        final Query query = this.entityManager.createNamedQuery("Changes.getById");
        query.setParameter("status", Status.POST_FLIP);
        List<Changes> changes = query.getResultList();
        for (Changes change : changes) {
            this.entityManager.remove(change);
        }
    

    欢迎任何其他解释或建议。