for ilustration purposes, lets say I have a Student table with some data and one School table . The Student table has a Foreign Key to School table. Using Spring data I have something like this:
<code> @Repository
public interface StudentRepositoryJpaSpecificationExecutor extends JpaSpecificationExecutor<Student > {
static Specification<Student> isSchoolAtLondon() {
Root<Student> studentRoot = query.from(Student.class);
Join<Student, School> schoolJoin = studentRoot.join("school");
return (root, query, cb) -> cb.equal(schoolJoin.get("city"), "London");
}
static Specification<Student> isSchoolExpensive() {
Root<Student> studentRoot = query.from(Student.class);
Join<Student, School> schoolJoin = studentRoot.join("school");
return (root, query, cb) -> cb.greaterThanOrEqualTo(schoolJoin.get("costPerYearUSD"), 10000L);
}
}
</code>
<code> @Repository
public interface StudentRepositoryJpaSpecificationExecutor extends JpaSpecificationExecutor<Student > {
static Specification<Student> isSchoolAtLondon() {
Root<Student> studentRoot = query.from(Student.class);
Join<Student, School> schoolJoin = studentRoot.join("school");
return (root, query, cb) -> cb.equal(schoolJoin.get("city"), "London");
}
static Specification<Student> isSchoolExpensive() {
Root<Student> studentRoot = query.from(Student.class);
Join<Student, School> schoolJoin = studentRoot.join("school");
return (root, query, cb) -> cb.greaterThanOrEqualTo(schoolJoin.get("costPerYearUSD"), 10000L);
}
}
</code>
@Repository
public interface StudentRepositoryJpaSpecificationExecutor extends JpaSpecificationExecutor<Student > {
static Specification<Student> isSchoolAtLondon() {
Root<Student> studentRoot = query.from(Student.class);
Join<Student, School> schoolJoin = studentRoot.join("school");
return (root, query, cb) -> cb.equal(schoolJoin.get("city"), "London");
}
static Specification<Student> isSchoolExpensive() {
Root<Student> studentRoot = query.from(Student.class);
Join<Student, School> schoolJoin = studentRoot.join("school");
return (root, query, cb) -> cb.greaterThanOrEqualTo(schoolJoin.get("costPerYearUSD"), 10000L);
}
}
If I want to use both specifications in a query, there will be a duplicated Join to “School” table in the SQL query. So:
- Is there a way to reuse inside the Specification class the Joins like singleton classes in order to avoid the duplicated Joins and avoid too the outer classes to pass in the Join objects?
- The option 1 is recommended or its better to pass in the Join objets from outside the class to the Specification methods that need them?
Thanks