How to get all referenced entities for a specific entity instance in JPA

Viewed 13

In my project, I'm trying to implement some Entities with one parent and multiple children by JPA & Hibernate like this:

/********** parent type **********/
@Entity
@Table(name = "t_parent")
public class Parent {
    @Id
    @Column(name = "f_id")
    private Long id;
}

/********** children types **********/
@Entity
@Table(name = "t_child_a")
public class ChildA {
    @Id
    @Column(name = "f_id")
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "f_parent")
    private Parent parent;
}

@Entity
@Table(name = "t_child_b")
public class ChildB {
    @Id
    @Column(name = "f_id")
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "f_parent")
    private Parent parent;
}

Because there will be more Children Types in the future, so relationships are only declared on the children side by annotation "ManyToOne", and there is no corresponding "OneToMany" on the parent side.

When delete a parent entity, any exist relationship will cause ConstraintViolationException from database.

My purpose is to find out that is there any children instance who has referenced to a specific parent instance, so i can give a clear and meaningful message to user, or any best practices for such situation?

1 Answers

As JPA deals with entities not tables you'll likely have to use multiple queries to check if each child type has a reference to the parent that is penned for deletion. You can check it like this using JPQL

boolean childAExists = em.createQuery("SELECT CASE WHEN COUNT(c) > 0 THEN TRUE ELSE FALSE END FROM ChildA c WHERE c.parent = :parent", Boolean.class)
                .setParameter("parent", parent)
                .getSingleResult();

boolean childBExists = em.createQuery("SELECT CASE WHEN COUNT(c) > 0 THEN TRUE ELSE FALSE END FROM ChildB c WHERE c.parent = :parent", Boolean.class)
                .setParameter("parent", parent)
                .getSingleResult();

If you're using Spring Data JPA you can probably simplify to this

boolean exists = existsByParent(parent);

If you don't want to perform multiple queries then a native query is your best bet

Related