8

我正在使用 JPA2 和 Hibernate 实现。

我有这样的简单映射:

@Entity 
class Topic {

    @Id
    @GeneratedValue(strategy = IDENTITY)

    int id;

   @OneToOne(cascade = ALL)
   @JoinColumn(name = "id_poll")
   private Poll poll;

}

@Entity 
class Poll {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    int id;
}

现在,当我删除也在 Topic 中的 Poll 对象时,我得到一个错误。

java.sql.SQLException:完整性约束违反 FKCC42D924982D3F4B 表:语句中的 TOPICS [从 id=? 的投票中删除]

我知道这是因为如果轮询记录在另一个表中有引用,我无法删除它。我怎么解决这个问题?我必须在主题表中手动设置 poll = null 还是有更好的解决方案?

4

4 回答 4

6

这是预期的行为:

双向关系的一个常见问题是应用程序更新了关系的一侧,但另一侧没有得到更新,并且变得不同步。在 JPA 中,就像在 Java 中一般,维护关系是应用程序或对象模型的责任

来源:对象损坏,关系的一侧在更新另一侧后没有更新

处理此问题的正确位置是在 @PreRemove 回调中:

@Entity 
class Poll {

    ...

    @PreRemove
    private void preRemove() {
        Poll poll = topic.getPoll();
        topic.setPoll( null );
    }
}

另请参阅:让 JPA/Hibernate 复制“ON DELETE SET NULL”功能

于 2012-08-24T23:31:51.127 回答
2

I was not able to find a solution by now, so before I delete a Poll object I always get a Topic object which contains given Pool and set it to null.

Topic topic = entityManager.find( Topic.class, 1 );
Poll poll = topic.getPoll();
topic.setPoll( null );
entityManager.remove( poll );

And it works correctly.

于 2011-01-04T13:05:23.693 回答
1

看起来 JPA 2 中的 @OneToOne 注释包含一个 orphanRemoval 标志,您可以尝试设置它并查看它是否可以优雅地删除它。

于 2011-01-03T02:58:51.153 回答
0

问题在于您在双方都使用自动生成的 ID。当您持久化父实体时,子实体也会被持久化,但它在父实体中的 ID 不会使用从数据库生成的 ID 进行更新。

因此,当您删除父级时,您不会删除子级,因为子级没有 ID。

尝试手动设置子实体的 ID,orphanRemoval 将起作用。

于 2011-12-20T10:32:31.740 回答