开发者

Hibernate @ManyToOne remove entry at One side, set FK to NULL at Many side

开发者 https://www.devze.com 2023-03-17 11:57 出处:网络
I\'m trying to learn to work with Hibernate but probably i don\'t understand @ManyToOne and inverse relations. I have two entities Author and Department. One Author has one Department, One Department

I'm trying to learn to work with Hibernate but probably i don't understand @ManyToOne and inverse relations. I have two entities Author and Department. One Author has one Department, One Department has Many Authors.

When I remove Author, nothing should happen with Department. When I remove Department, FK in Author's table should be updated to NULL value (Author should NOT be removed).

I've found nice explanation of inversion and figured out that Author is an owning side and according to this thread when I remove child (Department) the FK should be set to NULL. But it doesn't happen because only Department is removed and FK remains in Author table (which leads to org.hibe开发者_运维问答rnate.ObjectNotFoundException: No row with the given identifier exists).

When I add CascadeType.REMOVE to @OneToMany annotation in Department entity then all Authors tied to Department are also removed. Neither of aforementioned states are desirable. I just want to remove Department and set FK in Author table to NULL. How to do that?

Author and Department entities with annotations:

@Entity
@Table(name = "author")
public class Author implements Serializable {

    @Id
    @Column(name = "idauthor")
    @GeneratedValue
    private Integer idAuthor;

    @DepartmentFormat
    @ManyToOne
    @JoinColumn(name = "department", nullable = true)
    private Department department;
}

@Entity
@Table(name="department")
public class Department implements Serializable {

    @Id
    @Column(name="iddepartment")
    @GeneratedValue
    private Integer iddepartment;

    @OneToMany(mappedBy = "department", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    private Set<Author> authors;
}

Thanks in advance


There is no automatic way of setting all the foreign keys to null when some entity is removed. You have to explicitely get all the authors of the department, set their departement to null, and then remove the department.

You could also use a bulk update query to do this:

update Author a set a.department = null where a.department = :department

(and thus have just one query instead of n + 1), but be aware that the version field won't be updated, that there won't be any optimistic locking check, and that the already loaded departments of the session won't be affected (in memory) if you do so.

Note that you shouldn't have an ObjectNotFoundException when you're deleting an entity referenced by another one. Instead, you should enable a foreign key constraint in the database so that the removal of the department fails if there is still an author referencing it. That way, your data stays in a coherent state.

0

精彩评论

暂无评论...
验证码 换一张
取 消