我有两个相关的分支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可以做到吗?
答案 0 :(得分:3)
只需使用Hibernate注释添加它:
@OnDelete(action=OnDeleteAction.CASCADE)
生成外键为:“ON UPDATE NO ACTION ON DELETE CASCADE;”
但是没有动作= OnDeleteAction.SET_NULL
此外,如果可能的话,我不喜欢将我的代码绑定到Hibernate(但如果它有效,我可以忍受它。)
这thread讨论了它。我无法相信JPA(或Hibernate扩展)中没有一个简单的方法来生成外键。
答案 1 :(得分:2)
在您的情况下,您将从类生成数据库。这意味着您不会将数据库用于其他目的(因为这样做会强制您使用DDL脚本)。这意味着在数据库或java代码中实现此规则并不重要。
我们也知道Hibernate会在一个人会删除一个或多个状态并尝试在没有级联提交的情况下引用它时引发一个瞬态异常。
此外,将使用外键约束生成数据库。
所有这些意味着必须遵守约束才能使应用程序正常工作。
如果您的实体本身位于jar中,则可以在警报或状态界面中添加瞬态方法,以便在遵守规则时删除状态。
此外,程序员在使用实体时将被迫遵守规则,否则代码将无法工作。但是为了使任务更容易,您可以将关系设置为双向,以便从状态中跟踪警报的任务变得更容易。
如果可以,请使用ondelete拦截器/侦听器将alarm.status属性设置为null。
答案 2 :(得分:1)
不知道其他非hibernate实现,但这里是一个JIRA问题我在Hibernate中一直关注这个...
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2707
答案 3 :(得分:0)
您确定使用@OneToOne吗? 在我看来,你宁愿使用@ManyToOne(因为状态会受到几个警报的影响):
@Entity
public class Alarm {
...
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="idStatus", nullable=true)
private Status status;
...
}
答案 4 :(得分:-1)
OpenJPA
@ForeignKey(deleteAction=ForeignKeyAction.NULL)
但是没有标准的JPA方法(显然Hibernate不可能)。
让我想回到JDO。