Issue
We have 3 entities A, B, and C. We are searching in table A with fields within B and C. And the mapping is unidirectional, so B and Collection is not defined in A. We are using Spring Specification, how can we perform join in this case without converting the mapping to bidirectional?
@Entity
public class A {
@Id
Long id
String name
}
@Entity
public class B {
@Id
Long id
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "a_id")
A a;
@Column
String country;
}
@Entity
public class C {
@Id
Long id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "a_id")
private A a;
}
For example, if B is defined in A like that
@Entity
public class A {
@Id
Long id
String name
@OneToOne(mappedBy = "request")
private B b;
}
the join will be like that
public static Specification<A> countryEquals(String country) {
return (root, query, builder) -> builder.equal(
root.join("b", JoinType.LEFT).get("country"), country);
}
But B is not defined in A, then how to apply the join?
Solution
you can try to join it by B itself, you create a new Root and image you add a where b.a_id = a.id
to your query or here, you CriteriaBuilder, then you can add more predicate to look for fields in B table. Something like this, somewhat pseudo code cause I don't have my code here atm and write it down by my memory, but I hope it can help
public static Specification<A> countryEquals(String country) {
return (root, query, builder) -> (
Root<B> b_root = query.from(B.class);
Predicate b_join = builder.equal(b_root.get("a_id"), root.get("id"))
Predicate b_country = builder.equal(b_root.get("country"), country) // or like with `%country%`
return builder.and(other_predicate,...., b_join, b_country)
)
}
Answered By - Tan Sang
Answer Checked By - Candace Johnson (JavaFixing Volunteer)