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

如何在Hibernate中处理原生Native Query返回的JSON类型值?

问题原因

报错No Dialect mapping for JDBC type: 1111是因为PostgreSQL返回的JSON/JSONB类型属于JDBC的OTHER类型(对应编码1111),Hibernate默认的PostgreSQL方言没有对该类型做映射配置,因此无法直接转换为Java对象。


可行方案

方案1:扩展PostgreSQL方言,全局注册JSON类型映射

该方案全局生效,后续所有JSON类型返回都无需额外配置。

  1. 自定义方言类,继承你当前使用的PostgreSQL方言,注册JSON类型映射:
import org.hibernate.dialect.PostgreSQL10Dialect;
import com.vladmihalcea.hibernate.type.json.JsonNodeBinaryType;
import java.sql.Types;

public class CustomPostgreSQLDialect extends PostgreSQL10Dialect {
    public CustomPostgreSQLDialect() {
        super();
        // 映射JSONB类型到Jackson的JsonNode,如需映射普通JSON替换为JsonNodeStringType.class.getName()
        this.registerHibernateType(Types.OTHER, JsonNodeBinaryType.class.getName());
    }
}
  1. 在项目配置文件中修改Hibernate方言指向自定义类:
# application.yml 配置示例
spring:
  jpa:
    properties:
      hibernate:
        dialect: com.yourproject.config.CustomPostgreSQLDialect

方案2:使用注解显式指定字段JSON类型

如果不需要全局配置,可直接在对应返回类的字段上指定类型映射:

  1. 引入对应版本的hibernate-types依赖,在返回字段上添加@Type注解:
import com.vladmihalcea.hibernate.type.json.JsonType;
import org.hibernate.annotations.Type;
import com.fasterxml.jackson.databind.JsonNode;

// DTO或实体类示例
public class FieldDetailDTO {
    private Long mapDetailsId;
    private Integer rowId;
    @Type(JsonType.class)
    private JsonNode data;
    // 省略构造方法、getter、setter
}
  1. 如果你使用Hibernate 6及以上版本,无需额外引入依赖,直接使用官方自带的JSON类型注解即可:
import jakarta.persistence.Column;
import org.hibernate.type.SqlTypes;
import org.hibernate.annotations.JdbcTypeCode;
import com.fasterxml.jackson.databind.JsonNode;

public class FieldDetailDTO {
    private Long mapDetailsId;
    private Integer rowId;
    @JdbcTypeCode(SqlTypes.JSON)
    private JsonNode data;
    // 省略构造方法、getter、setter
}

方案3:通过SqlResultSetMapping指定查询结果映射

如果是使用原生查询返回自定义DTO,可通过@SqlResultSetMapping显式指定JSON列的类型:

import com.vladmihalcea.hibernate.type.json.JsonType;
import jakarta.persistence.SqlResultSetMapping;
import jakarta.persistence.ConstructorResult;
import jakarta.persistence.ColumnResult;

@SqlResultSetMapping(
    name = "FieldDetailMapping",
    classes = @ConstructorResult(
        targetClass = FieldDetailDTO.class,
        columns = {
            @ColumnResult(name = "map_details_id", type = Long.class),
            @ColumnResult(name = "row_id", type = Integer.class),
            @ColumnResult(name = "data", type = JsonType.class)
        }
    )
)

Repository层查询指定映射即可:

@Query(value = "SELECT map_details_id,row_id,json_object_agg(key, value) AS data FROM field_details_tbl where map_details_id=:mapId GROUP BY row_id,map_details_id ORDER BY row_id",
    nativeQuery = true,
    resultSetMapping = "FieldDetailMapping")
List<FieldDetailDTO> getFieldDetails(@Param("mapId") Long mapId);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:36:06