Spring Data JPA原生查询解析错误:升级Spring Boot 3.2.0后结果异常
Spring Boot 3.2.0升级后原生查询接口投影解析jsonb列异常
问题背景
原技术栈为Spring Boot 3.0.4,使用接口投影结合原生JPA查询,投影接口定义了Optional<Set<String>> getValue();方法,直接映射数据库中jsonb类型的字符串数组列。实体类中该列配置如下:
@Type(io.hypersistence.utils.hibernate.type.json.JsonBinaryType.class) @Column(name = "value", columnDefinition = "jsonb", nullable = false) private Set<String> value = new HashSet<>();
升级至Spring Boot 3.2.0后,原生查询返回结果异常:预期解析为["value1", "value2"]格式的Set<String>,实际得到被字符串包裹的数组["[\"value1\", \"value2\"]"]。
原因分析
Spring Boot 3.2.x同步升级了Spring Data JPA与Hibernate版本,原生查询结合接口投影时,自定义类型(如JsonBinaryType)的映射逻辑发生了变化。旧版本中Hibernate会自动对原生查询结果应用类型转换器解析jsonb列,新版本则直接返回数据库存储的原始字符串形式,未触发类型转换流程。
解决方案
方案1:数据库层显式解析jsonb列(PostgreSQL适配)
在原生SQL中调用PostgreSQL的jsonb_array_text函数,直接将jsonb数组解析为字符串数组,投影接口可直接映射为Set<String>:
SELECT id, jsonb_array_text(value) AS value FROM your_table WHERE ...
方案2:改用类投影手动解析
接口投影在复杂类型映射上存在局限,改用类投影并手动处理json解析逻辑:
public class EntityProjection { private final Long id; private final Optional<Set<String>> value; // 构造方法接收数据库返回的json字符串,手动解析为Set<String> public EntityProjection(Long id, String valueJson) { this.id = id; if (valueJson == null) { this.value = Optional.empty(); return; } try { Set<String> values = new ObjectMapper().readValue( valueJson, new TypeReference<Set<String>>() {} ); this.value = Optional.of(values); } catch (JsonProcessingException e) { this.value = Optional.empty(); } } // Getter方法 public Long getId() { return id; } public Optional<Set<String>> getValue() { return value; } }
Repository中返回该类投影:
@Query(nativeQuery = true, value = "SELECT id, value FROM your_table WHERE ...") List<EntityProjection> findProjections();
方案3:强制Hibernate应用自定义类型映射
在配置文件中添加Hibernate参数,确保原生查询结果触发自定义类型解析:
spring.jpa.properties.hibernate.type.preferred_json_type=io.hypersistence.utils.hibernate.type.json.JsonBinaryType
同时确认JsonBinaryType已通过Hibernate的TypeContributor正确注册(若未自动注册,需手动配置类型贡献者)。
内容的提问来源于stack exchange,提问作者Кирилл
相关产品推荐
相关产品推荐

