JPA set null on delete

Java

I am sure a lot of you heard, when talking about RDBMS systems about a foreign key with “Set NULL on delete”. It means that if a record in the parent table is deleted, then the corresponding records in the child table will have the foreign key fields set to NULL. The records in the child table will not be deleted. A foreign key with set null on delete can be created at the beginning when a table gets created (CREATE TABLE statement) or later on (ALTER TABLE statement).

I needed the same type of behavior, but done in my DAO layer where I happened to use Java Persistence API.

Following is the solution. We will be working with 2 entities, here is are some simple implementations of a Child class and a Parent class.

@Entity
@Table(name = "c_child")
public class Child {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }
}
@Entity
@Table(name = "c_parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
    private Set<Child> children;

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Set<Child> getChildren() {
        return children;
    }

    public void setChildren(Set<Child> children) {
        this.children = children;
    }

    @PreRemove
    private void removeParentFromChildren() {
        for (Child child : this.getChildren()) {
            child.setParent(null);
        }
    }
}

With this setup in place whenever the parent will be removed from the storage ( entitymanager.remove(parent) ), after/if the transaction is commited, all the children that had the deleted parent will now have null. So, as you can see the solution is a simple callback method annotated with the JPA provided @PreRemove. A callback method is a no-arg method with no return type and any arbitrary name. The callback I used is only one of the many that JPA API provides

Type Description
@PrePersist Executed before the entity manager persist operation is
actually executed or cascaded. This call is synchronous with the
persist operation.
@PreRemove Executed before the entity manager remove operation is
actually executed or cascaded. This call is synchronous with the
remove operation.
@PostPersist Executed after the entity manager persist operation is
actually executed or cascaded. This call is invoked after the
database INSERT is executed.
@PostRemove Executed after the entity manager remove operation is
actually executed or cascaded. This call is synchronous with the
remove operation.
@PreUpdate Executed before the database UPDATE operation.
@PostUpdate Executed after the database UPDATE operation.
@PostLoad Executed after an entity has been loaded into the current
persistence context or an entity has been refreshed.