【问题标题】:Query for multiple values of the same property with queryDSL and Spring Data JPA使用 queryDSL 和 Spring Data JPA 查询同一属性的多个值
【发布时间】:2021-03-14 13:40:12
【问题描述】:

有没有办法使用 Spring DataREST JPA 和 querydsl 查询同一属性的多个值?我不确定查询 URL 的格式应该是什么,以及是否需要在绑定中进行额外的自定义。我在文档中找不到任何东西。如果我的数据库中有一个“学生”表,其中有一个“专业”列和相应的学生实体,我会假设查询所有具有“数学”和“科学”专业的学生看起来像 http://localhost:8080/学生?专业=数学&专业=科学。然而,在这个查询中,只有第一部分被采用,major=science 被忽略

【问题讨论】:

    标签: spring-data-jpa spring-data-rest querydsl


    【解决方案1】:

    以下示例自定义Querydsl web 支持以在操作中执行收集。 URI /students?major=sword&major=magic["sword", "magic"] 中搜索具有major 的学生。

    实体和存储库

    public class Student {
    
        private Long id;
    
        private String name;
    
        private String major;
    }
    
    public interface StudentRepos extends PagingAndSortingRepository<Student, Long>,
                                          QuerydslPredicateExecutor<Student>,
                                          QuerydslBinderCustomizer<QStudent> {
    
        @Override
        default void customize(QuerydslBindings bindings, QStudent root) {
    
            bindings.bind(root.major)
                    .all((path, value) -> Optional.of(path.in(value)));
        }
    }
    

    测试数据

    new Student("Arthur", "sword");
    new Student("Merlin", "magic");
    new Student("Lancelot", "lance");
    

    控制器

    @RestController
    @RequestMapping("/students")
    @RequiredArgsConstructor
    public class StudentController {
    
        private final StudentRepos studentRepos;
    
        @GetMapping
        ResponseEntity<List<Student>> getAll(Predicate predicate) {
    
            Iterable<Student> students = studentRepos.findAll(predicate);
            return ResponseEntity.ok(StreamSupport.stream(students.spliterator(), false)
                                                  .collect(Collectors.toList()));
        }
    }
    

    测试用例

        @Test
        @SneakyThrows
        public void queryAll() {
    
            mockMvc.perform(get("/students"))
                   .andExpect(status().isOk())
                   .andExpect(jsonPath("$").isArray())
                   .andExpect(jsonPath("$", hasSize(3)))
                   .andDo(print());
        }
    
        @Test
        @SneakyThrows
        void querySingleValue() {
    
            mockMvc.perform(get("/students?major=sword"))
                   .andExpect(status().isOk())
                   .andExpect(jsonPath("$").isArray())
                   .andExpect(jsonPath("$", hasSize(1)))
                   .andExpect(jsonPath("$[0].name").value("Arthur"))
                   .andExpect(jsonPath("$[0].major").value("sword"))
                   .andDo(print());
        }
    
    
        @Test
        @SneakyThrows
        void queryMultiValue() {
    
            mockMvc.perform(get("/students?major=sword&major=magic"))
                   .andExpect(status().isOk())
                   .andExpect(jsonPath("$").isArray())
                   .andExpect(jsonPath("$", hasSize(2)))
                   .andExpect(jsonPath("$[0].name").value("Arthur"))
                   .andExpect(jsonPath("$[0].major").value("sword"))
                   .andExpect(jsonPath("$[1].name").value("Merlin"))
                   .andExpect(jsonPath("$[1].major").value("magic"))
                   .andDo(print());
        }
    

    完整的 Spring Boot 应用程序在 Github

    【讨论】:

    • 多值绑定如何在具有多对多关系的连接表上工作?假设我有课程表并通过连接表将课程连接到学生。如何搜索修读多门课程的学生?
    • 我不擅长querydsl。如果您向我展示如何构造Collection.containsAll(Collection) querydsl 调用,将会有所帮助。因为只有CollectionExpressionBase.contains(E child) 而没有CollectionExpressionBase.containsAll(...)。然后将其应用于 StudentRepos.customize()。
    猜你喜欢
    • 2014-03-29
    • 2012-11-09
    • 2020-06-16
    • 1970-01-01
    • 2016-02-17
    • 2018-11-03
    • 1970-01-01
    • 2015-05-11
    • 2017-10-31
    相关资源
    最近更新 更多