Wilhelm Sorban
Wilhelm Sorban

Reputation: 1131

Hibernate lazy fetch - getting child objects

My understanding is that, by default, Hibernate will set the FetchType to lazy, for all relation types.

In my case, I have a bi-directional OneToMany-ManyToOne relationship, as follows:

Parent class:

public class Parent{

    @Id
    @Column(name = "parent_id")
    private long parentId;

    @OneToMany(mappedBy = "parent")
    @JsonIgnore
    private List<Child> children;

    public List<Child> getChildren()
    {
        return this.children;
    }
}

Child class:

public class Child
{
    private String name;

    @ManyToOne(optional = false) //every child must have a parent
    @JoinColumn(name = "parent_id")
    private Parent parent;

    public Child(Parent parent, String name)
    {
        this.parent = parent;
        this.name = name;
    }
}

Child service:

public class ChildService
{
    public List<Child> getChildren(long parentId)
    {
        Parent parent = getParentRepository().findOne(parentId);
        return parent.getChildren(); //This returns null
    }

    public Child getNamedChild(long parentId)
    {
        Parent parent = getParentRepository().findOne(parentId);
        //??????????????? 
        //Not sure how to get the children of this specific parent, 
        //which has a specific name.
    }
}

Parent repository:

public interface ParentRepository extends JpaRepository<Parent, Long> {
}

I have two problems here:

When I call the method getChildren() in ChildService, it returns null. The database does contain the right data. I will need to get these with LAZY fetch type. I have tried to invoke a "parent.getChildren().size()" method, before returning, but it still returns null.

The other problem is how do I get a child that has a specific name? Is it possible to do it via the Repository? Or do I need to getChildren(parentId), and iterate until I find the one that is named in a specific way?

EDIT: After some suggestions, I went on and implemented my ChildRepository this way:

public interface ChildRepository extends JpaRepository<Child, Long> {
    @Query("SELECT child FROM Parent parent JOIN parent.child AS child WHERE parent.parentId = :parentId")
    List<Child> getChildren(@Param("parentId") String parentId);
    @Query("SELECT child FROM Parent parent JOIN arent.child AS child WHERE parent.parentId = :parentId AND child.childId = :childId")
    Child getChildByName(@Param("childId") Long childId, @Param("parentId") String parentId);
}

Upvotes: 2

Views: 4444

Answers (1)

toongeorges
toongeorges

Reputation: 1966

Can you inject the EntityManager in the ChildService class? I cannot fully verify the code below, but you could try something like

public class ChildService
{
    private EntityManager em;

    public List<Child> getChildren(long parentId)
    {
        Query query = em.createQuery("SELECT c FROM Parent p JOIN FETCH p.children AS c WHERE p.parentId = :parentId");
        query.setParameter("parentId", parentId);
        return (List<Child>) q.getResultList();
    }

    public Child getNamedChild(long parentId, String name)
    {
        Query query = em.createQuery("SELECT c FROM Parent p JOIN FETCH p.children AS c WHERE p.parentId = :parentId AND c.name = :name");
        query.setParameter("parentId", parentId);
        query.setParameter("name", name);
        return (Child) q.getSingleResult();
    }
}

Upvotes: 3

Related Questions