我有一个 Spring Data JPA 存储库(在 postgres 数据库上),有时我需要使用 nativeQuery = true 选项来使用本机查询。
但是在我目前的情况下,我需要传递一个订单字段,并且这样做:
电话..
targetStatusHistoryRepository.findSirenAlarmTimeActivation([uuid,uuid2],"activation_name DESC", 0, 10)
.. 回购方法
@Query(
nativeQuery = true,
value = """select
a.name as activation_name,
min(transition_from_active_in_millis),
max(transition_from_active_in_millis),
avg(transition_from_active_in_millis) from target_status_history t, activation_scenario a
where t.activation_uuid=a.activation_scenario_id and t.transition_from_active_in_millis > 0 and t.activation_uuid in (:activationUUIDs) group by a.name,t.activation_uuid
order by :orderClause offset :offset limit :limit """
)
List<Object[]> findSirenAlarmTimeActivation(@Param("activationUUIDs") List<UUID> activationUUIDs,
@Param("orderClause") String orderClause, @Param("offset") int offset, @Param("limit") int limit )
我用 DESC 编写了一个单元测试,然后用 ASC 调用,反之亦然,似乎第一个调用是什么,第二个调用给出了相同的结果。
如果这是一个准备好的语句,并且是在
ORDER BY
子句中提供的绑定值,那么这是有效的,但是...
提供的绑定值不会被解释为 SQL 文本。也就是说,该值将被视为只是一个值(如文字字符串)。它不会被视为列名称或
ASC
或 DESC
关键字。
在您的声明上下文中,为
:orderClause
绑定占位符提供一个值,这将具有与您编写 ORDER BY 'some literal'
相同的效果。
这根本没有真正对行进行任何排序。
(至少在我使用过的 DB2、Teradata、Oracle、SQL Server、MySQL 和 MariaDB(JDBC、Perl DBI、ODBC、Pro/C 等)的每个 SQL 客户端库中都是如此。)
(MyBatis 确实提供了一种方便的机制,可以在 SQL 文本中进行变量替换,在准备 SQL 文本之前动态更改 SQL 文本,但这些替换是在准备语句之前处理的,并且不会变成语句中的绑定占位符。)
通过 ORDER BY 子句中一些精心设计的表达式可以获得一些“动态”排序。例如,我们可以让静态 SQL 文本如下所示:
ORDER BY CASE WHEN :sort_param = 'name ASC' THEN activation_name END ASC
, CASE WHEN :sort_param = 'name DESC' THEN activation_name END DESC
(这里的SQL文本不是动态的,它实际上是静态的,就像我们写的一样。
ORDER BY expr1 ASC
, expr1 DESC
“技巧”是 ORDER BY 子句中的表达式有条件地返回每行中某个列的值,或者返回一个文字(在上面的示例中,文字 NULL),具体取决于 a 的值绑定值,在执行时评估。
最终效果是我们可以“动态”获得以下任一效果:
ORDER BY activation_name ASC, NULL DESC
或
ORDER BY NULL ASC, activation_name DESC
或
ORDER BY NULL ASC, NULL DESC
取决于我们为 :sort_param 占位符提供的值。
使用 createNativeQuery 并直接将按值排序作为字符串附加到查询中,而不是使用 setParameter()。对我来说效果很好。
我在 Spring Boot 中使用本机查询也遇到了同样的问题,我发现的方法是:
1- 创建可分页:
Pageable pageable = PageRequest.of(numPage, sizePage, Sort.by(direction , nameField));
2- 在查询中添加“
ORDER BY true
”,例如:
@Query(value = " SELECT * " +
"FROM articulos a " +
"WHERE " +
"AND a.id = :id" +
"ORDER BY TRUE",
countQuery = " SELECT * " +
"FROM articulos a " +
"WHERE " +
"AND a.id = :id" +
"ORDER BY TRUE"
, nativeQuery = true)
Page<PrecioArticuloVO> obtenerPreciosPorCategoriaProveedor(@Param("id")Long id,Pageable pagina);
经过这么多次尝试,我尝试了下面的一个,它对我有用。
@查询(“选择 a.name 作为activation_name, 分钟(transition_from_active_in_millis), 最大值(transition_from_active_in_millis), 来自 target_status_history t 的 avg(transition_from_active_in_millis),activation_scenario a 其中 t.activation_uuid=a.activation_scenario_id 和 t.transition_from_active_in_millis > 0 且 (:activationUUIDs) 中的 t.activation_uuid 按 a.name、t.activation_uuid 分组” ) 列表
findSirenAlarmTimeActivation(UUIDList, PageRequest.of(offset, pageSize, Sort.by(Sort.Order.asc(sortBy))));
就是这样,它对我有用,分页,排序