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适配:
- 实体类属性注解更新:
@Type(JsonBinaryType.class) @Column(columnDefinition="jsonb") private EnrichExpn expn; @Type(JsonBinaryType.class) @Column(columnDefinition="jsonb") private EnrichExpnScratch expnScratch;
- 原生查询参数设置指定二进制类型实例:
.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
相关产品推荐
相关产品推荐

