我正在用springdatajpa开发一个spring引导应用程序。我正在使用一个定制的jpql查询按某个字段分组并获取计数。下面是我的存储库方法。
@Query(value = "select count(v) as cnt, v.answer from Survey v group by v.answer")
public List<?> findSurveyCount();
其工作和结果如下:
[
[1, "a1"],
[2, "a2"]
]
我想得到这样的东西:
[
{ "cnt":1, "answer":"a1" },
{ "cnt":2, "answer":"a2" }
]
我怎样才能做到这一点?
9条答案
按热度按时间bkhjykvo1#
我使用自定义dto(接口)将本机查询Map到—这是最灵活、最安全的重构方法。
我遇到的问题是,令人惊讶的是,接口中字段的顺序和查询中列的顺序很重要。我通过按字母顺序排列接口getter,然后以同样的方式排列查询中的列来实现它。
4ioopgfo2#
我知道这是一个老生常谈的问题,它已经得到了回答,但这里有另一种方法:
jhdbpxl93#
jpql查询解决方案
jpa规范中的jpql查询支持这一点。
步骤1:声明一个简单的bean类
步骤2:从存储库方法返回bean示例
重要注意事项
确保提供bean类的完全限定路径,包括包名。例如,如果调用bean类
MyBean
而且是打包的com.path.to
,指向bean的完全限定路径将是com.path.to.MyBean
. 只是提供MyBean
不会工作(除非bean类在默认包中)。确保使用
new
关键字。SELECT new com.path.to.MyBean(...)
会有用的,但是SELECT com.path.to.MyBean(...)
不会的。确保传递属性的顺序与bean构造函数中预期的顺序完全相同。尝试以不同的顺序传递属性将导致异常。
确保查询是有效的jpa查询,也就是说,它不是本机查询。
@Query("SELECT ...")
,或@Query(value = "SELECT ...")
,或@Query(value = "SELECT ...", nativeQuery = false)
会有用的,但是@Query(value = "SELECT ...", nativeQuery = true)
不起作用。这是因为本机查询是在没有修改的情况下传递给jpa提供者的,并且是针对底层rdbms执行的。自new
以及com.path.to.MyBean
如果不是有效的sql关键字,rdbms将抛出异常。本机查询解决方案
如上所述
new ...
语法是jpa支持的机制,适用于所有jpa提供者。但是,如果查询本身不是jpa查询,即它是本机查询,则new ...
语法将不起作用,因为查询直接传递给底层rdbms,后者不理解new
关键字,因为它不是sql标准的一部分。在这样的情况下,bean类需要用spring数据投影接口替换。
步骤1:声明投影接口
步骤2:从查询返回投影属性
使用sql
AS
关键字将结果字段Map到投影属性以进行明确Map。yvt65v4c4#
我不喜欢查询字符串中的java类型名,并用特定的构造函数来处理它。spring jpa在hashmap参数中使用查询结果隐式调用构造函数:
代码需要lombok来解析@getter
js4nwp545#
上面的代码对我有用。
tgabmvqs6#
我刚刚解决了这个问题:
基于类的投影不适用于本机查询(
@Query(value = "SELECT ...", nativeQuery = true
))因此,我建议使用接口定义自定义dto。在使用dto之前,应该验证查询的语法是否正确
yeotifhr7#
定义一个定制的pojo类say sureveyqueryanalytics并将查询返回值存储在定制的pojo类中
jfgube3f8#
此sql查询返回列表<object[]>将显示。
你可以这样做:
dphi5xsq9#
使用接口可以得到更简单的代码。不需要创建和手动调用构造函数
步骤1:用必需字段声明intefrace:
步骤2:在接口中选择与getter同名的列,并从存储库返回intefrace方法: