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

使用@Query查询User列表触发ClassCastException异常求助

问题描述

将JSON字段的依赖从io.hypersistence:hypersistence-utils-hibernate-62替换为Hibernate原生的@JdbcTypeCode(SqlTypes.JSON)实现后,部署在Linux K8s环境时触发类型转换异常,本地MacOS环境可正常运行。


相关代码

仓库层实现

package com.user.Dao;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.user.Entities.User;

@Repository
public interface UserRepository extends CrudRepository<User,Long> {
    

    @Query("""
            SELECT new com.user.UserProfileProjection(emails)
            FROM User
            WHERE id = :id""")
    Optional<UserProfileProjection> findProfileById(Long id);
}


public record UserProfileProjection(List<RestUserEmail> emails) {
    
    @SuppressWarnings("unchecked")
    public UserProfileProjection(Object emails) {
        this(((List<UserEmail>) emails).stream().map(e -> new RestUserEmail(e.email(), e.language())).toList());
    }

    public record RestUserEmail(String email, Language language)
}

修改前的User实体(使用Hypersistence工具)

import io.hypersistence.utils.hibernate.type.json.JsonBinaryType;
import org.hibernate.annotations.Type;

public class User extends AbstractAggregateRoot<User> {
    ...
    @Type(JsonBinaryType.class)
    private List<UserEmail> email;


    public record UserEmail(String email, Language language) {

    }
}

修改后的User实体(使用Hibernate原生JSON支持)

import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

public class User extends AbstractAggregateRoot<User> {
    ...
    @JdbcTypeCode(SqlTypes.JSON)
    private List<UserEmail> email;


    public record UserEmail(String email, Language language) {

    }
}

错误信息

java.lang.ClassCastException: class com.user.Dao.UserData$UserEmail cannot be cast to class java.util.List (package com.user.Dao.User$UserEmail is in unnamed module of loader org.springframework.boot.loader.launch.LaunchedClassLoader @f6f2d33; java.util.List is in module java.base of loader 'bootstrap')

解决方案

1. 对齐Spring Boot与Hibernate版本兼容性

确保使用的Spring Boot版本(建议3.2+)与Hibernate 6.x完全适配,部分旧版Spring Boot对Hibernate原生JSON类型的跨环境处理存在缺陷。

2. 调整JPQL查询逻辑

Hibernate原生JSON类型在JPQL中直接投影集合时,易出现序列化/反序列化的环境差异。改为先查询完整实体,再在业务层转换投影:

// 仓库层修改
@Query("SELECT u FROM User u WHERE id = :id")
Optional<User> findByIdForProfile(Long id);

// 业务层转换
public Optional<UserProfileProjection> getProfile(Long id) {
    return userRepository.findByIdForProfile(id)
            .map(user -> new UserProfileProjection(user.email()));
}

3. 修复投影构造器的类型处理

原构造器依赖强制类型转换,跨环境类加载器可能导致类型识别异常,改为显式类型校验:

public UserProfileProjection(Object emails) {
    this(convertToRestEmails(emails));
}

private static List<RestUserEmail> convertToRestEmails(Object emails) {
    if (emails instanceof List<?> list) {
        return list.stream()
                .filter(item -> item instanceof UserEmail)
                .map(item -> (UserEmail) item)
                .map(e -> new RestUserEmail(e.email(), e.language()))
                .toList();
    }
    throw new IllegalArgumentException("Invalid emails type: " + emails.getClass());
}

4. 明确数据库JSON字段定义

在实体字段上添加columnDefinition,确保数据库端字段类型与Hibernate映射一致(以PostgreSQL为例):

@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition = "jsonb")
private List<UserEmail> email;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:53:28