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

Kotlin Hibernate 泛型KClass查询列表时Criteria类型不匹配报错

报错本质
  • 当传入泛型化的KClass<*>时,编译器对criteriaBuilder.createQuery(clazz.java)的泛型推导出现偏差,最终生成的CriteriaQuery被识别为CriteriaQuery<Nothing>类型。
  • 此时criteria.select()方法要求传入与CriteriaQuery泛型完全匹配的Selection<out Nothing>,但criteria.from(clazz.java)返回的Root<out Any>泛型边界和要求的Nothing不匹配,直接触发类型校验报错。
  • 传入固定实体类(如Country::class.java)时,编译器可以明确推导出匹配的CriteriaQuery<Country>、Root<Country>类型,泛型链路完全对齐,因此不会出现报错。
修复方案

基础兼容实现

手动修正泛型推断的偏差,对齐类型边界,最小改动消除编译报错:

fun getListSize(clazz: KClass<*>): Int {
    hibernate.openSession().use { session ->
        val cb = session.criteriaBuilder
        // 显式指定CriteriaQuery的泛型为Any,消除Nothing的错误推断
        val criteria = cb.createQuery(Any::class.java) as CriteriaQuery<Any>
        val root = criteria.from(clazz.java)
        criteria.select(root)

        val query = session.createQuery(criteria)
        return query.resultList.size
    }
}

注意:原实现缺少Session资源关闭逻辑,新增的use代码块会在方法逻辑执行完成后自动关闭会话,避免数据库连接泄漏。

性能优化实现

原实现会把实体全量查询到内存后再统计大小,数据量较大时会占用大量内存,可直接调整为数据库层面执行count统计,性能更高:

fun getListSize(clazz: KClass<*>): Long {
    hibernate.openSession().use { session ->
        val cb = session.criteriaBuilder
        val criteria = cb.createQuery(Long::class.java)
        val root = criteria.from(clazz.java)
        // 直接在数据库端统计实体总数,无需拉取全量实体数据到内存
        criteria.select(cb.count(root))

        return session.createQuery(criteria).singleResult
    }
}
额外说明
  • 不要为了绕开报错对所有类型加无边界强制转换,避免后续运行时出现类转换异常。
  • 泛型场景下的Criteria查询,尽量通过显式指定Query的泛型参数来消除编译器的不确定推断,比无意义的强转更稳定。

内容的提问来源于stack exchange,提问作者displayThisName

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 11:24:05