注释映射与 XML 映射和删除实体

Annotation mapping vs. XML mapping and deleting an entity

我正在将项目从 XML 映射迁移到基于纯 JPA 注释的映射,我 运行 在尝试删除(删除)实体及其子实体时遇到了问题。它适用于 XML 映射,不适用于注释映射。

XML 映射如下所示:

<set name="evaluations" order-by="evalDate desc" table="Evaluation" lazy="true" inverse="true" cascade="delete">
    <key column="requestId" />
    <one-to-many class="org.stuff.model.Evaluation" />
</set>

注释映射,据我所知是这样的:

@OneToMany(orphanRemoval=true)
@JoinColumn(name = "requestId")
@OrderBy("evalDate DESC")
private Set<Evaluation> evaluations = new TreeSet<>();

这是一个单向关系。

删除实体的 JPA 代码是:

ServiceRequest sr = em.getReference(ServiceRequest.class, id);
em.remove(sr);

其中上面的EvaluationServiceRequest的子对象。 Hibernate 4.3.7 是我正在使用的 JPA Impl,运行 在 WildFly 8.2 上。

将 Hibernate 设置为 barf out 其 SQL,使用 annotation 映射执行删除 Hibernate 会生成查询以查找实体引用,然后在何时remove 被调用它产生一个更新,试图将 Evaluation FK 中的子记录更新回 ServiceRequest 为空:

Hibernate: update Evaluation set requestId=null where requestId=?

因为 requestId.

上有 not null 约束,所以爆炸了

如果我使用 XML 映射(参见上面的代码片段)执行相同的操作,它就可以正常工作。所有子实体都与父实体一起删除。如果从不尝试 更新 任何东西,Hibernate 只会生成 selectsdeletes

感觉好像注解映射错了,但又想不通哪里错了。请帮忙。

我认为您需要指定级联注释。当心this issue though.

感谢@troy 的指导。单独添加级联不起作用,但添加 insertable=flase, updateable=false 可以。所以注释映射现在看起来像这样:

@OneToMany(cascade=CascadeType.REMOVE)
@JoinColumn(name = "requestId", insertable=false, updatable=false)
@OrderBy("evalDate DESC")
private Set<Evaluation> evaluations = new TreeSet<>();

我不确定为什么会这样,所以如果有人能解释一下,我将不胜感激。

我是间接来到这里的。首先,我向此映射添加了一个 nullable-false,当我部署它时,Hibernate 抱怨它并告诉我我需要在 Evaluation 实体上将 insert=false update=false 添加到 requestId。那种工作。我可以随意删除,但无法保存或插入评价。我有点期待那会发生。所以我只是厌倦了这个解决方案并且它起作用了。

你 xml 配置实际上说你的 ServiceRequest 和 Set 之间的关系是双向的,因为 inverse = "true"。

但是您的 JPA 注释是单向的。所以这应该有效(在 OP 的评论后编辑)

@OneToMany(orphanRemoval=true,mappedBy="requestId")
@OrderBy("evalDate DESC")
private Set<Evaluation> evaluations = new TreeSet<>();

这里 mappedBy="requestId" 告诉 Hibernate 这是关系的所有者端。因此它将发布声明以删除评估。