Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to define LEFT Join when annotating a relationship with @OneToMany?

I have the following scenario

@Entity
public class Parent {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
    private Set<Child> children;
   }
@Entity
public class Child {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch=FetchType.LAZY, optional = false)
    private Parent parent;
}

When building queries with either JPA Criteria or JPQL I get a inner join by default when requesting a join fetch for children.

Either by using:

SELECT p from Parent p JOIN p.children

OR

EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Parent> query = cb.createQuery(Parent.class);

Root<Parent> root = query.from(Parent.class);
root.fetch(Parent_.children);
query.distinct(true);

List<Parent> result = em.createQuery(query).getResultList();

How I can avoid this default behavior(inner join)? My goal is to get LEFT JOIN by default when specifying OneToMany relationship... Is it possible without setting JoinType.LEFT explicitly when building a query?

Any help is really appreciated. Thank you in advance

like image 859
rodrigoArantes Avatar asked Nov 01 '22 09:11

rodrigoArantes


1 Answers

Is it possible without setting JoinType.LEFT explicitly when building a query?

No, it's not! The implicit join is the INNER JOIN which is assumed if you navigate the association in the JPQL query.

You have to use the LEFT JOIN and FETCH in case you need the child association to be fetched as well:

SELECT p 
from Parent p 
LEFT JOIN FETCH p.children

or with Criteria API:

EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Parent> query = cb.createQuery(Parent.class);

Root<Parent> root = query.from(Parent.class);
root.fetch(Parent_.children, JoinType.LEFT);
query.distinct(true);

List<Parent> result = em.createQuery(query).getResultList();
like image 86
Vlad Mihalcea Avatar answered Nov 14 '22 23:11

Vlad Mihalcea