如何使用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>的直接映射:
- 添加Maven依赖(根据你的Hibernate版本选择对应版本):
<dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-55</artifactId> <version>2.20.0</version> </dependency>
- 定义视图实现类并配置结果映射:
// 视图实现类 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; } }
- 更新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
相关产品推荐
相关产品推荐

