删除实体时休眠将外键设置为空
Posted
技术标签:
【中文标题】删除实体时休眠将外键设置为空【英文标题】:Hibernate set foreign key to null when delete entity 【发布时间】:2013-06-11 16:16:25 【问题描述】:我有以下休眠实体:
@Entity
@Table(name = "model_view")
public class ModelView
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "modelView_id")
private Integer id;
@ManyToOne
@NotNull
@JoinColumn(name = "page_id", nullable = false, insertable = true, updatable = true)
private Page page;
/* getters and setters */
还有:
@Entity
public class Page
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "page_id")
private Integer id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "page_id")
@IndexColumn(name = "modelView_id")
private Set<ModelView> modelViews = new HashSet<ModelView>();
/* getters and setters */
当我在 DAO 中删除实体 «ModelView» 时出现异常:
ORA-01407: unable to replace ("MODEL_VIEW"."PAGE_ID") to NULL
怎么了?为什么hibernate在删除前设置外键为NULL?
【问题讨论】:
【参考方案1】:为什么hibernate在删除前设置外键为NULL?
Hibernate 尝试通过将 FK 清空来取消引用您尝试删除的记录。不幸的是,在大多数情况下,FK 不能为空。您必须告诉 Hibernate 在删除 Page
记录时不要更新 ModelView
实例。
尝试在page
中的@JoinColumn
映射上将insertable
和updatable
更改为false ModelView
:
@JoinColumn(name = "page_id", nullable = false, insertable = false, updatable = false)
使用这些值时,ModelView
记录将保留。同样,如果您强制执行参照完整性,这将不起作用。要解决这个问题,您需要打开级联删除。我注意到在您的代码中您已经在使用 CascadeType.ALL
应该可以正常工作。
这是一个解释这些字段的 SO Q&A:
In JPA why and how to use insertable and updatable parameter?
我有一个类似的问题,通过使用 false
来解决这些值。
How can I map "insert='false' update='false'" on a composite-id key-property which is also used in a one-to-many FK?
【讨论】:
这不是我的解决方案,因为在这种情况下,我在插入实体 «ModelView» 时遇到相同的错误(ORA-01400:无法将 NULL 插入(“MODEL_VIEW”。“PAGE_ID”))。我尝试将 FK 设置为可为空,但这不是一个好主意。还有其他解决办法吗? 这个建议的解决方案应该也可以用 INSERT 语句解决这个问题。当您将insertable
和updatable
设置为false
时,您是在告诉Hibernate 您将手动处理保存对ModelView
记录的修改。这意味着您需要先插入/更新Page
记录,然后在ModelView
上设置FK,然后独立保存这些记录,最好是全部在1 个事务中。如果你这样做,你永远不会遇到 FK 为 NULL 的情况。
@AnEi 如果你仍然有这些错误,你能分享一些你用来导致它的代码吗?
将“insertable = false, updatable = false”添加到@JoinColumn 规范对我来说起到了作用。谢谢!然后 Hibernate 问题只会按正确的顺序删除,不会尝试将 FK 更新为 null。
@MaksimGumerov 你不应该在ModelView.page
上设置updatable = false
,你应该在Page.modelViews
上设置它。仍然可以通过在代码中设置 ModelView.page 来更新数据库中的 ModelView.page_id 字段,只是无法使用代码中的 Page.modelViews 更新 FK。如果您仍然感到困惑,请提出一个新问题,这样您将获得更多帮助。随时在这里链接到新问题,我会看看。以上是关于删除实体时休眠将外键设置为空的主要内容,如果未能解决你的问题,请参考以下文章