是否可以使用Spring Data Jpa Specification中的特定列进行分组?

我具有使用RSQL(我使用this库)和规范来对数据库的where子句进行过滤器调用的功能。

我查询的模型非常简单:它只包含一堆属性,与其他模型没有任何关系。

存储库(我使用 JpaSpecificationExecutor 的通知):

public interface BaseRepository<M extends BaseModel> extends JpaRepository<M,Long>,JpaSpecificationExecutor<M>{

}

因此,我以字符串的形式获取过滤条件(我在运行时获取它们),然后创建一个新的规范,该规范将用于生成带where子句的结果sql查询。

在服务中,我使用指定符调用存储库方法 findAll

String filter = "createdDate > 2019-09-04T11:52:59.449";
return repository.findAll(toSpecification(filter),pageable).getcontent();  

现在,我需要添加新功能,该功能允许按运行时获得的某些特定字段进行分组,因此我不知道确切将使用哪些字段。

因此,通过创建新的规范并将其与原始规范组合,我设法将分组按节添加到结果sql查询中:

String filter = "createdDate > 2019-09-04T11:52:59.449";

Specification<M> groupBySpec = new Specification<M>() {

            @Override
            public Predicate toPredicate(Root<M> root,CriteriaQuery<?> query,CriteriaBuilder criteriaBuilder) {

                List<Expression<?>> groupByParams = new ArrayList<>();

                groupByParams.add(root.get("param1"));
                groupByParams.add(root.get("param2"));

                query.groupBy(groupByParams);

                // Here I try to select specific columns
                query.multiselect(root.get("column1"),root.get("column2")).distinct(true);

                return query.getGroupRestriction();
            }
        };


return repository.findAll(groupBySpec.and(toSpecification(filter)),pageable).getcontent(); 

但是我得到了一个SQL异常ERROR: column "columnName" must appear in the GROUP BY clause or be used in an aggregate function

此操作的结果,因为它实际上选择了所有列,而忽略了我的query.multiselect

我尝试仅使用Criteria Api而不使用JPA规范来实现它,例如:

public List<Object[]> getallWithSpecific(){

        CriteriaBuilder cb = em.getcriteriaBuilder();
          CriteriaQuery<Object[]> q = cb.createQuery(Object[].class);
          Root<Model> c = q.from(Model.class);


        List<Expression<?>> groupByParams = new ArrayList<>();

        groupByParams.add(c.get("column1"));
        groupByParams.add(c.get("column2"));

        q.groupBy(groupByParams);
          q.select(cb.array(c.get("column1"),c.get("column2"),cb.count(q.from(Model.class))));

          return em.createQuery(q).getResultList();

    }

它确实有效,它只是选择了我需要的东西。但是,我不能仅以这种方式使用它,因为我需要将此 group by 功能与我先前介绍的过滤器,分页功能结合使用。

由于JpaRepository按照给定模型的条件工作,所以我不知道如何对它说“只抓住我需要的列,而不是整个模型”

我还尝试向jpa存储库中添加一个用@Query("actual jpql query")注释的方法,我可以在其中描述选择的内容:

@Query("select m.column1,m.column2,count(*) from Model m group by m.column1,m.column2")
    List<Object[]> customMethod();

它也起作用。因此,现在它了解到即使我仍然可以在同一模型的条件下使用它,我也只需要抓住特定的列即可。

我也了解 projections ,它实际上是一个接口,我可以在其中定义列以选择和使用它,例如:List<Projection> findAll()。 但这不是我的情况,不如使用@Query,因为我在运行时检索要选择的组的列,所以它是动态的,而不是静态的。

总结:可以使用Jpa规范选择特定的列,而无需添加描述选择内容的新类(这就是@Query的工作原理,它只是从jpql查询中获取所有内容,而无需任何其他类\接口,也可以)。也许我需要重写jpa repo的方法findAll以返回List<Object[]>,就像它与@Query和纯Criteria Api一起使用一样?

maoyink 回答:是否可以使用Spring Data Jpa Specification中的特定列进行分组?

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3151302.html

大家都在问