10

我有两个相关的类 JPA 注释。警报和状态。一个警报可以有一个状态。

我需要的是能够删除一个状态并将空值“传播”到已删除的状态中的警报。

也就是说,我需要将外键定义为“ on delete set null ”。

@Entity
public class Alarm {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence")
    @SequenceGenerator(name="sequence", sequenceName="alarm_pk_seq")
    private Integer id;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="idStatus")
    private Status status;

    // get/set
}

@Entity
public class Status {
    @Id
    @Column(name="idStatus")
    private Integer id;

    private String description;

    // get/set
}

例子:

前:

STATUS
id  description
1   new
2   assigned
3   closed

ALARMS
id  status
1   1
2   2
3   2

之后(删除id=2的状态)

STATUS
id  description
1   new
3   closed

ALARMS
id  status
1   1
2   NULL
3   NULL

我正在使用 Hibernate 和 PostgreSQL,从源代码自动生成数据库。我已经尝试了所有可能的 CascadeType 都没有成功。

代码有什么问题吗?可以用 JPA 做到这一点吗?

4

5 回答 5

3

只需使用 Hibernate 注释添加:

@OnDelete(action=OnDeleteAction.CASCADE)

将外键生成为:“ON UPDATE NO ACTION ON DELETE CASCADE;”

但是没有action=OnDeleteAction.SET_NULL

此外,如果可能的话,我不喜欢将我的代码绑定到 Hibernate(但如果它有效,我可以接受它)。

这个线程讨论它。我不敢相信 JPA(或 Hibernate 扩展)中没有一种简单的方法来生成外键。

于 2009-01-25T15:36:28.313 回答
2

在您的情况下,您正在从类生成数据库。这意味着您不会将数据库用于其他目的(因为这样做会迫使您拥有 DDL 脚本)。这意味着在数据库或 java 代码中实现此规则并不重要。

我们还知道 Hibernate 会在删除一个或多个状态并尝试在没有级联的情况下提交时引用它的情况下引发瞬态异常。

此外,数据库将使用外键约束生成。

这意味着必须遵守约束才能使应用程序正常工作。

如果您的实体自己在一个罐子里,您可以在警报或状态界面中添加一个临时方法以在遵守规则的同时删除状态。

此外,程序员在使用实体时将被迫遵守规则,否则代码将无法工作。但是为了使任务更容易,您可以使关系双向,以便从状态中跟踪警报的任务变得更容易。

如果可以,请使用 ondelete 拦截器/侦听器将 alarm.status 属性设置为 null。

于 2009-02-06T15:56:53.843 回答
1

不知道其他非休眠实现,但这是我在休眠中一直关注的一个 JIRA 问题......

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2707

于 2009-06-09T06:55:38.310 回答
0

你确定你的@OneToOne 吗?在我看来,您宁愿使用 @ManyToOne (因为状态可能会受到多个警报的影响):

@Entity
public class Alarm {
    ...

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="idStatus", nullable=true)
    private Status status;

    ...
}
于 2009-01-22T08:40:16.773 回答
-1

OpenJPA 有

@ForeignKey(deleteAction=ForeignKeyAction.NULL)

但是没有标准的 JPA 方法可以做到这一点(显然使用 Hibernate 是不可能的)。

让我想回到 JDO。

于 2012-10-15T20:19:43.100 回答