Spring Data JPA多条件关联查询实现求助
实现多条件关联查询的修正方案
先修正现有代码的错误
你当前的Test1Specifications里,root.join("ids")是错误的,因为Test1实体中关联Test2的属性是test2,应该改为root.join("test2")。
完整实现所有过滤条件
我们需要把三个条件(t2.key='keyNames'、t2.value IN 传入列表、t1.createdDate >= 12小时前)通过CriteriaBuilder组合成查询条件,以下是修正后的Test1Specifications:
import org.springframework.data.jpa.domain.Specification; import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.Predicate; import java.time.LocalDateTime; import java.util.List; public class Test1Specifications { public static Specification<Test1> hasTestWithValueAndTimeRange(List<String> values) { return (root, query, criteriaBuilder) -> { // 关联Test2表 Join<Test1, Test2> test2Join = root.join("test2"); // 条件1:t2.key = 'keyNames' Predicate keyPredicate = criteriaBuilder.equal(test2Join.get("key"), "keyNames"); // 条件2:t2.value IN 传入的values列表 Predicate valuePredicate = test2Join.get("value").in(values); // 条件3:t1.createdDate >= 当前时间减去12小时 LocalDateTime twelveHoursAgo = LocalDateTime.now().minusHours(12); Predicate timePredicate = criteriaBuilder.greaterThanOrEqualTo(root.get("createdDate"), twelveHoursAgo); // 组合所有条件,用AND连接 return criteriaBuilder.and(keyPredicate, valuePredicate, timePredicate); }; } }
调整Service层调用
修改Test1Service中的getIds方法,使用上面的完整Specification:
import java.util.List; import java.util.stream.Collectors; public class Test1Service { private final Test1Repository test1Repository; private final Test2Repository test2Repository; public Test1Service(Test1Repository test1Repository, Test2Repository test2Repository) { this.test1Repository = test1Repository; this.test2Repository = test2Repository; } public List<Long> getIds(List<String> values) { Specification<Test1> filters = Test1Specifications.hasTestWithValueAndTimeRange(values); return test1Repository.findAll(filters) .stream() .map(Test1::getId) .collect(Collectors.toList()); } }
额外说明
- 你原来的SQL用了
LEFT OUTER JOIN,但后续WHERE t2.key = 'keyNames'会把左连接变成内连接(因为过滤了t2的非空条件),所以上面的代码用root.join("test2")(默认内连接)是符合实际查询逻辑的;如果确实需要保留左连接,可改为root.join("test2", JoinType.LEFT),但此时要注意处理NULL值的情况。 createdDate字段是LocalDateTime类型,Spring Data JPA会自动处理与数据库时间类型的转换,无需手动调用to_timestamp函数。- 返回类型从
List<String>改为List<Long>更合理,因为Test1的Id是Long类型。
内容的提问来源于stack exchange,提问作者perplexedDev
相关产品推荐
相关产品推荐

