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
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With