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

Hibernate6.2-JPA:原生查询插入jsonb列时无法确定推荐JdbcType

解决PostgreSQL jsonb列原生批量插入的JDBC类型匹配问题

环境

  • Java 17
  • Spring Boot 3.1.0
  • Hibernate 6.2.2.Final
  • PostgreSQL 12

问题

使用原生查询向PostgreSQL的jsonb列批量插入数据时,触发「Could not determine recommended JdbcType for」错误,业务要求必须使用原生查询实现批量插入。

已尝试的两种方案(均未解决)

方案1:使用hypersistence-utils的@Type(JsonType.class)

实体类属性配置:

@Type(JsonType.class)
@Column(columnDefinition="jsonb")
private EnrichExpn expn;

@Type(JsonType.class)
@Column(columnDefinition="jsonb")
private EnrichExpnScratch expnScratch;

原生查询代码:

String query = "INSERT INTO cust_enrich(cust_id, correlation_id, expn, expn_scratch) " +
               "values(:cust_id, :correlation_id, :expn, :expn_scratch) ON CONFLICT DO NOTHING ";

var queryRun =
        entityManager
            .createNativeQuery(query)
            .unwrap(Query.class)
            .setParameter("cust_id", t.getCustId())
            .setParameter("correlation_id", t.getCorrelationId())
            .setParameter("expn", t.getExpn(), JsonType.INSTANCE)
            .setParameter("expn_scratch", t.getExpnScratch(), JsonType.INSTANCE);
queryRun.executeUpdate();

方案2:使用Hibernate的@JdbcTypeCode(SqlTypes.JSON)

实体类属性配置:

@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition="jsonb")
private EnrichExpn expn;

@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition="jsonb")
private EnrichExpnScratch expnScratch;

原生查询代码:

String query = "INSERT INTO cust_enrich(cust_id, correlation_id, expn, expn_scratch) " +
               "values(:cust_id, :correlation_id, :expn, :expn_scratch) ON CONFLICT DO NOTHING ";

var queryRun =
        entityManager
            .createNativeQuery(query)
            .unwrap(Query.class)
            .setParameter("cust_id", t.getCustId())
            .setParameter("correlation_id", t.getCorrelationId())
            .setParameter("expn", t.getExpn(), SqlType.class)
            .setParameter("expn_scratch", t.getExpnScratch(), SqlType.class);
queryRun.executeUpdate();

正确解决方法

针对方案1(hypersistence-utils)的修正

PostgreSQL的jsonb列对应二进制JSON类型,需替换为JsonBinaryType适配:

  1. 实体类属性注解更新:
@Type(JsonBinaryType.class)
@Column(columnDefinition="jsonb")
private EnrichExpn expn;

@Type(JsonBinaryType.class)
@Column(columnDefinition="jsonb")
private EnrichExpnScratch expnScratch;
  1. 原生查询参数设置指定二进制类型实例:
.setParameter("expn", t.getExpn(), JsonBinaryType.INSTANCE)
.setParameter("expn_scratch", t.getExpnScratch(), JsonBinaryType.INSTANCE);

针对方案2(Hibernate原生注解)的修正

设置参数时不能传递SqlType.class,需指定具体的JDBC类型:

方式1:使用JsonJdbcType实例

.setParameter("expn", t.getExpn(), JsonJdbcType.INSTANCE)
.setParameter("expn_scratch", t.getExpnScratch(), JsonJdbcType.INSTANCE);

方式2:直接传入SQL类型代码

.setParameter("expn", t.getExpn(), SqlTypes.JSON)
.setParameter("expn_scratch", t.getExpnScratch(), SqlTypes.JSON);

批量插入优化

如果需要批量插入多条数据,建议用Hibernate批处理机制提升效率:

String query = "INSERT INTO cust_enrich(cust_id, correlation_id, expn, expn_scratch) " +
               "values(:cust_id, :correlation_id, :expn, :expn_scratch) ON CONFLICT DO NOTHING ";

var queryRun = entityManager.createNativeQuery(query).unwrap(Query.class);

for (YourEntity t : entityList) {
    queryRun.setParameter("cust_id", t.getCustId())
            .setParameter("correlation_id", t.getCorrelationId())
            .setParameter("expn", t.getExpn(), JsonBinaryType.INSTANCE) // 适配方案1的类型,或替换为方案2的类型
            .setParameter("expn_scratch", t.getExpnScratch(), JsonBinaryType.INSTANCE)
            .addBatch();
}

queryRun.executeBatch();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:58:18