进行本机查询时,Spring @Query无法处理位置参数

时间:2018-07-25 08:52:42

标签: hibernate spring-boot kotlin spring-data

我正在尝试使用spring数据进行本地查询。该查询具有JPQL不支持它们的子查询,因此我必须使用本机查询。我需要的最终查询如下:

@Query( value = """select count(*)
    from (select * from image a where a.table_id = ?1) as img
    inner join
        (select b.id from image_set b where b.camera_id = ?2 and b.time between ?3 and ?4) as imgset
    on img.image_set_id = imgset.id""",
        nativeQuery = true)

fun countByTableIdAndImageSetTimeBetween(tableId: Long, cameraId: Long, fromDateTime: LocalDateTime, toDateTime: LocalDateTime): Long

这没有提供结果,因此暂时我替换了一个简单的查询来尝试查找问题。在下文中,我将引用此查询,直到至少可以运行该查询为止。

@Query( value = "select count(*) from image_set b where b.camera_id = ?2", nativeQuery = true)

fun countByTableIdAndImageSetTimeBetween(tableId: Long, cameraId: Long, fromDateTime: LocalDateTime, toDateTime: LocalDateTime): Long

我遇到的第一个问题是我遇到了异常:

org.hibernate.QueryException: Named parameter [2] not set

经过一些搜索,我发现虽然JPA的位置参数是1索引的,而Hibernate的位置参数是0索引的。我发现错误可能是由于尝试将LocalDateTime分配给查询中无法使用的位置而引起的,在执行本机查询时,我应该使用0索引。这似乎很成问题,但将?2更改为?1 did 可以解决该异常。但是,它不能解决问题。我现在总是得到0的结果,事实并非如此。 我注意到在休眠日志中未填写参数值:

Hibernate: 
/* dynamic native SQL query */ select
    count(*) 
from
    image_set b 
where
    b.camera_id=?

但是,其他查询似乎也是这种情况,它可以工作,所以我猜冬眠没有记录它发送的实际查询吗?无论如何,到现在我已经迷路了。我不知道我在做什么错,任何帮助将不胜感激。

重要附录: 我的可疑假设是在执行本机查询时位置参数基于0。这实际上是错误的。我刚尝试使用?0,但我得到ArrayIndexOutOfBoundsException:-1。这样看来,弹簧本身会从索引中减去1。

这改变了问题:使用?1时返回0的原因确实是因为我使用了错误的值。在这种情况下,0是正确的响应。 因此,我需要弄清楚的是为什么在使用?2时出现错误。

1 个答案:

答案 0 :(得分:0)

解决了这个问题,这里有一些需要解压的东西。我主要是愚蠢。

所以让我们从我实际想要的查询开始,该查询始终返回0:

ld message.obj -o message.exe

不起作用的原因不是位置参数。这是时间争论。在事后看来,这很痛苦,但花了我一段时间后才知道:当然,您不能在本地查询中使用LocalDateTime作为参数。您必须将其转换为java.util.Date。

这样可以解决我实际上想解决的问题。其余的几乎是追赶鹅。因为我认为查询不起作用的唯一合理假设是参数传递错误,所以我在同一方法上进行了第二次简化查询,因为这是最少的工作:

@Query( value = """select count(*)
    from (select * from image a where a.table_id = ?1) as img
    inner join
        (select b.id from image_set b where b.camera_id = ?2 and b.time between ?3 and ?4) as imgset
    on img.image_set_id = imgset.id""",
        nativeQuery = true)

fun countByTableIdAndImageSetTimeBetween(tableId: Long, cameraId: Long, fromDateTime: LocalDateTime, toDateTime: LocalDateTime): Long

问题在于此查询不会查询同一实体!这是在错误的存储库中,因为我只是将其放在其他方法上,而又无法正常工作的原因再次出现不是由于位置参数。将查询移到正确的存储库后,它实际上可以正常工作。
最终导致我得出结论的是,也许这些参数毕竟不是我的问题,并且经过一番严峻的考验之后,我才意识到问题所在。

有两点需要记录: 一,不,使用nativeQuery时,您不需要从零开始的索引作为位置参数。 Spring会从索引本身中减去1。

二,不,实际上,使用@Query注释时,方法名称根本不重要。您可以将您的方法命名为fooBar,然后执行任何查询,无论您要使用多少参数,它都无济于事。

谢谢大家的努力!