繁体   English   中英

Spring Boot JPA查询生成器以获取汇总值?

[英]Spring boot jpa query builder for aggregate values?

我想创建可输出汇总值的可定制查询。 我知道三种获取和执行查询的方法,但是似乎都不足够。 我要构建的查询如下所示:

Select max(category), min(price) as minprice from mytable where k='v' group by category

tldr:跳过1和2。

  1. SQL作为字符串
    • private NamedParameterJdbcTemplate template; template.query("select ..." , new MapSqlParameterSource("...", "...") , rs -> {...rs.getString("minprice")...
    • 亲:我们可以从查询中访问结果
    • 缺点:它没有使用查询生成器:我们必须自己构建“ select ...”字符串。
  2. 使用储存库
    • public interface MytableRepository extends CrudRepository<Mytable, Integer> { @Query("Select ...") public List<Object[]> findMinMaxPrice(@Param("myParam") String myParam);
    • 优点:我们可以从查询中访问结果。
    • 缺点:查询是硬编码的
  3. 使用查询生成器
    • Specification<MyTable> spec = Specifications.<>where((mytable, query, cb) -> { Predicate sql = cb.equal(mytable.get("k"), "v"; return sql; } List<Mytable> result = myJpaSpecificationExecutor.findall(spec);
    • 优点:正在使用查询生成器
    • 缺点:查询未使用groupBy。 由于我们的groupBy查询不是返回Mytable类的Mytable而是聚集值,因此我看不到如何进行这项工作。 我开始从Mytable选择,所以我认为我需要将其用作Specification类型参数,但这立即意味着结果也应该是MyTable类型,不是吗?

如何使用具有灵活结果类型的查询生成器?

您可以考虑使用jOOQ,可以这样给您带来尽可能多的灵活性,同时可以将查询保持在“代码中”状态。

它可以从您的数据库模式生成Java类,您可以使用它使用其DSL进行查询。 这是一个示例: https : //github.com/benjamin-bader/droptools/blob/master/droptools-example/src/main/java/com/bendb/example/resources/PostsResource.java#L99

这是我上面链接的代码的内容:

    final Record4<Integer, String, OffsetDateTime, String[]> record = create
            .select(BLOG_POST.ID, BLOG_POST.BODY, BLOG_POST.CREATED_AT, arrayAgg(POST_TAG.TAG_NAME))
            .from(BLOG_POST)
            .leftOuterJoin(POST_TAG)
            .on(BLOG_POST.ID.equal(POST_TAG.POST_ID))
            .where(BLOG_POST.ID.equal(id.get()))
            .groupBy(BLOG_POST.ID, BLOG_POST.BODY, BLOG_POST.CREATED_AT)
            .fetchOne();

它看起来有些时髦,但这是生成的内容:

SELECT blog_post.id, blog_post.body, blog_post.created_at, array_agg(post_tag.tags)
FROM blog_post
LEFT JOIN post_tag ON blog_post.id = post_tag.post_id
WHERE blog_post.id = ?
GROUP BY blog_post.id, blog_post.body, blog_post.created_at

您可以看到Java代码与生成的SQL非常相似,但是由于jOOQ生成的代码,它仍然是完全类型安全的。 因为它是代码,所以您可以根据需要动态构建查询。

这是一个很严重的依赖关系,但是如果您的SQL需求是专门的或动态的,它可以为您做很多事情。

我不知道什么级别的灵活性足够好,但是如果您有一个实体超类,其中包含您感兴趣的所有字段,那么可以使用通用存储库

public interface MyGenericRepository<E extends MEntity> extends JpaRepository<E,Long> {

  @Query("select e from #{#entityName} e where u.someField = ?1 or e.someOtherField = ?1")
  List<E> findBySomeFieldOrSomeOtherField(String query);
}

文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM