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

如何使用Hibernate将Postgres的jsonb列映射为Java List<Enum>

解决Postgres jsonb列映射为List的简便方法

方法1:利用Postgres内置函数转换(无额外依赖)

在原生查询中通过Postgres的jsonb_array_elements_text将jsonb数组转为Postgres文本数组,Hibernate可直接映射为List<String>,再通过默认方法转换为枚举列表:

修改查询语句:

SELECT id,
       ARRAY(SELECT jsonb_array_elements_text(my_table.myEnums)) AS myEnums
FROM my_table
WHERE id IN (:ids)

更新视图接口,添加枚举转换的默认方法:

import java.util.List;
import java.util.stream.Collectors;

public interface MyView {
    Long getId();
    List<String> getMyEnums();

    default List<MyEnum> getMyEnumsAsEnum() {
        return getMyEnums().stream()
                .map(MyEnum::valueOf)
                .collect(Collectors.toList());
    }
}

调用时直接通过getMyEnumsAsEnum()获取枚举列表即可。

方法2:使用Hibernate Types库直接映射(推荐)

借助Hibernate Types提供的JsonBinaryType,实现jsonb列到List<MyEnum>的直接映射:

  1. 添加Maven依赖(根据你的Hibernate版本选择对应版本):
<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-55</artifactId>
    <version>2.20.0</version>
</dependency>
  1. 定义视图实现类并配置结果映射:
// 视图实现类
public class MyViewImpl implements MyView {
    private final Long id;
    private final List<MyEnum> myEnums;

    public MyViewImpl(Long id, List<MyEnum> myEnums) {
        this.id = id;
        this.myEnums = myEnums;
    }

    @Override
    public Long getId() {
        return id;
    }

    @Override
    public List<MyEnum> getMyEnums() {
        return myEnums;
    }
}
  1. 更新Repository的查询方法,指定结果映射:
import org.hibernate.type.descriptor.sql.JsonBinaryType;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.ConstructorResult;
import javax.persistence.ColumnResult;
import java.util.Collection;
import java.util.List;

@Query(nativeQuery = true, value = """
        SELECT id,
               my_table.myEnums AS myEnums
        FROM my_table
        WHERE id IN (:ids)
        """)
@SqlResultSetMapping(
        name = "MyViewMapping",
        classes = @ConstructorResult(
                targetClass = MyViewImpl.class,
                columns = {
                        @ColumnResult(name = "id", type = Long.class),
                        @ColumnResult(name = "myEnums", type = JsonBinaryType.class)
                }
        )
)
List<MyView> findAll(@Param("ids") Collection<Long> ids);

方法3:自定义AttributeConverter转换

编写Converter实现JSON字符串到List<MyEnum>的双向转换:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.util.Collections;
import java.util.List;

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

    @Override
    public String convertToDatabaseColumn(List<MyEnum> attribute) {
        try {
            return objectMapper.writeValueAsString(attribute);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert enum list to JSON", e);
        }
    }

    @Override
    public List<MyEnum> convertToEntityAttribute(String dbData) {
        if (dbData == null || dbData.isBlank()) {
            return Collections.emptyList();
        }
        try {
            return objectMapper.readValue(dbData, new TypeReference<List<MyEnum>>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert JSON to enum list", e);
        }
    }
}

修改查询语句,将jsonb转为文本:

SELECT id,
       my_table.myEnums::text AS myEnums
FROM my_table
WHERE id IN (:ids)

最后在视图接口的方法上指定Converter:

import javax.persistence.Convert;
import java.util.List;

public interface MyView {
    Long getId();

    @Convert(converter = JsonbToListEnumConverter.class)
    List<MyEnum> getMyEnums();
}

注:部分Spring Data JPA版本可能不支持在视图接口方法上直接使用@Convert,此时建议配合视图实现类使用。

内容的提问来源于stack exchange,提问作者dev-007

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:13:11