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

Hibernate 6.4原生查询如何将JSONB转换为ArrayList?

Hibernate 6.4 兼容6.1 jsonb自动转为ArrayList的解决方案

问题背景

在PostgreSQL环境下,以下Hibernate代码在6.1和6.4版本表现存在差异:

var rows =
   session
     .createNativeQuery("SELECT CAST('[1,2,3]' as jsonb) as data, 2 as id", Object[].class)
      .addScalar("data")
      .addScalar("id", StandardBasicTypes.INTEGER)
      .list();
rows.forEach(row -> System.out.println(row[0].getClass() + " -> " + row[0]));
  • Hibernate 6.1输出:
class java.util.ArrayList -> [1, 2, 3]
  • Hibernate 6.4输出:
class java.lang.String -> [1, 2, 3]

6.1版本会自动将jsonb数组转换为ArrayList,但6.4版本仅将该字段读取为String类型,尝试多种StandardBasicTypes均无法复现6.1的行为,需解决在6.4中实现相同转换效果的问题。

解决方案

方法1:显式指定JsonType映射

Hibernate 6.4中需要明确指定jsonb字段的类型为JsonType,并指定目标转换类型为List:

import org.hibernate.type.JsonType;

var rows =
   session
     .createNativeQuery("SELECT CAST('[1,2,3]' as jsonb) as data, 2 as id", Object[].class)
      .addScalar("data", JsonType.of(List.class))
      .addScalar("id", StandardBasicTypes.INTEGER)
      .list();

此方式可直接将jsonb数组转为ArrayList,与6.1版本行为一致。

方法2:自定义全局类型转换器

若需全局统一处理jsonb到List的转换,可自定义属性转换器:

  1. 实现AttributeConverter:
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

@Converter(autoApply = true)
public class JsonbToListConverter implements AttributeConverter<List<Object>, String> {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(List<Object> attribute) {
        try {
            return objectMapper.writeValueAsString(attribute);
        } catch (Exception e) {
            throw new RuntimeException("转换List为JSON字符串失败", e);
        }
    }

    @Override
    public List<Object> convertToEntityAttribute(String dbData) {
        try {
            return objectMapper.readValue(dbData, new TypeReference<List<Object>>() {});
        } catch (Exception e) {
            throw new RuntimeException("转换JSON字符串为List失败", e);
        }
    }
}
  1. 查询中指定使用该转换器对应的自定义类型:
import org.hibernate.type.CustomType;

var rows =
   session
     .createNativeQuery("SELECT CAST('[1,2,3]' as jsonb) as data, 2 as id", Object[].class)
      .addScalar("data", new CustomType(new JsonbToListConverter()))
      .addScalar("id", StandardBasicTypes.INTEGER)
      .list();

方法3:使用DTO映射(推荐)

定义与查询结果匹配的DTO类:

public class ResultDto {
    private List<Object> data;
    private Integer id;

    public ResultDto(List<Object> data, Integer id) {
        this.data = data;
        this.id = id;
    }

    // getter方法
    public List<Object> getData() {
        return data;
    }

    public Integer getId() {
        return id;
    }
}

将DTO作为查询返回类型,Hibernate会自动完成jsonb到List的映射:

var rows =
   session
     .createNativeQuery("SELECT CAST('[1,2,3]' as jsonb) as data, 2 as id", ResultDto.class)
      .list();
rows.forEach(dto -> System.out.println(dto.getData().getClass() + " -> " + dto.getData()));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:03:42