You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate随机抛出错误:无法将ArrayList强制转换为Long类型

Kotlin与Java互操作导致JPA Repository列表参数不稳定报错问题

使用Repository方法时遇到随机失败的错误,怀疑和Kotlin列表与Java的互操作性有关,具体是Kotlin列表在JPA处理时出现类型识别问题,导致参数绑定错误。


单元测试代码

@Test
fun `should return recipes with the specified author, locale and categories`() {
    println("AuthorID: " + author.id)

    recipeRepo.findRecipesBy(
        locale = LanguageSelection.ENGLISH,
        authorIds = arrayListOf(44),
    )
    // 还没到断言就抛出异常
}

Repository定义

interface RecipeRepository : JpaRepository<Recipe, Long> {

    @Query("SELECT r FROM Recipe r WHERE "
            + "(:authorIds is null or r.author.id in (:authorIds)) "
            + "and (:recipeIds is null or r.id in (:recipeIds)) "
            + "and (:minPrice is null or r.estimatedPrice >= :minPrice) "
            + "and (:maxPrice is null or r.estimatedPrice <= :maxPrice) "
            + "and ( cast(:beforeDate as timestamp) is null or r.createdAt < cast(:beforeDate as timestamp)) "
            + "and ( cast(:afterDate as timestamp) is null or r.createdAt > cast(:afterDate as timestamp)) "
            + "and (:minLikeCount is null or r.likeCount >= :minLikeCount) "
            + "and (:categoryIds is null or exists(select rc from r.categories rc where rc.id in (:categoryIds))) "
    )

    fun findRecipesBy(
        @Param("authorIds") authorIds: ArrayList<Long>? = null,
        @Param("recipeIds") recipeIds: ArrayList<Long>? = null,
        @Param("minPrice") minPrice: Double? = null,
        @Param("maxPrice") maxPrice: Double? = null,
        @Param("beforeDate") beforeDate: Date? = null,
        @Param("afterDate") afterDate: Date? = null,
        @Param("minLikeCount") minLikeCount: Int? = null,
        @Param("categoryIds") categoryIds: ArrayList<Long>? = null,
        sort: Sort = Sort.by(Sort.Direction.ASC, "createdAt"),
    ): List<Recipe>

}

报错信息

Parameter value [[44]] did not match expected type [BasicSqmPathSource(id : Long) ]
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [[44]] did not match expected type [BasicSqmPathSource(id : Long) ]
    at app//org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
    at app//org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235)
    at app//org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
    at app//org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at app//org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at app//org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
    at app//org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at app//org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:134)
    at app//org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at app//org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at app//org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at app//org.springframework.data.repository.core.support.MethodInvocationValidator.invoke(MethodInvocationValidator.java:94)
    at app//org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at app//org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218)
    at app/jdk.proxy3/jdk.proxy3.$Proxy189.findRecipesBy(Unknown Source)
    at app//com.fittastetic.fittastetic_backend.shared.recipe.repository.RecipeRepository$DefaultImpls.findRecipesBy$default(RecipeRepository.kt:38)
    ...
Caused by: org.hibernate.type.descriptor.java.CoercionException: Cannot coerce value `[44]` [java.util.ArrayList] as Long
    at app//org.hibernate.type.descriptor.java.LongJavaType.coerce(LongJavaType.java:155)
    at app//org.hibernate.type.descriptor.java.LongJavaType.coerce(LongJavaType.java:24)
    at app//org.hibernate.query.internal.QueryParameterBindingImpl.coerce(QueryParameterBindingImpl.java:144)
    at app//org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:111)
    ... 141 more

解决方案

  1. 替换Repository参数类型:将方法参数中的ArrayList<Long>?改为List<Long>?,JPA和Spring Data对通用List类型的兼容性更好,能避免具体集合实现类导致的类型识别异常:
fun findRecipesBy(
    @Param("authorIds") authorIds: List<Long>? = null,
    @Param("recipeIds") recipeIds: List<Long>? = null,
    // 其他参数保持不变
    @Param("categoryIds") categoryIds: List<Long>? = null,
    sort: Sort = Sort.by(Sort.Direction.ASC, "createdAt"),
): List<Recipe>
  1. 统一列表创建方式:调用Repository时使用Kotlin原生的listOf(),而非Java的arrayListOf(),减少跨集合类型的互操作问题:
recipeRepo.findRecipesBy(
    locale = LanguageSelection.ENGLISH,
    authorIds = listOf(44),
)
  1. 升级Hibernate版本:若问题仍存在,检查当前Hibernate版本是否对Kotlin集合有完善支持,建议升级到最新稳定版,修复潜在的类型绑定bug。

内容的提问来源于stack exchange,提问作者Just A Question

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:01:10