Hibernate6.3调用JPA executeUpdate更新Clob字段遇语义异常求助
解决Hibernate 6.3+JPA3.1中CriteriaUpdate更新Clob字段的SemanticException问题
问题背景
升级到Hibernate 6.3和JPA 3.1后,使用CriteriaUpdate更新Oracle数据库的Clob字段时抛出类型不匹配的语义异常,此前在Hibernate 5.2.18+JPA2.1环境下无此问题。
实体类Clob字段定义
@Column(name="DES_PDFSETTING_URPST") public Clob getDesPdfsettingUrpst() { return this.desPdfsettingUrpst; } public void setDesPdfsettingUrpst(Clob desPdfsettingUrpst) { this.desPdfsettingUrpst = desPdfsettingUrpst; }
原更新代码
CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaUpdate<UserReportSettings> update = cb.createCriteriaUpdate(UserReportSettings.class); Root e = update.from(UserReportSettings.class); update.set("desPdfsettingUrpst", ClobProxy.generateProxy(pdfSettings)); update.where(cb.equal(e.get("seqUrpstUrpst"), seq)); session.createQuery(update).executeUpdate();
异常信息
org.hibernate.query.SemanticException: Cannot assign expression of type 'java.io.Serializable' to target path 'alias_2044729830.desPdfsettingUrpst' of type 'java.sql.Clob' at org.hibernate.query.sqm.internal.TypecheckUtil.assertAssignable(TypecheckUtil.java:356) ...(省略部分栈信息)
可行解决方案
方案1:用CriteriaBuilder.literal()显式包装ClobProxy
Hibernate 6对类型校验更严格,直接传入ClobProxy会被识别为Serializable类型,通过literal()方法可以显式声明值的类型,绕过类型检查问题:
update.set("desPdfsettingUrpst", cb.literal(ClobProxy.generateProxy(pdfSettings)));
方案2:将实体类字段改为String类型(推荐)
如果业务场景允许,将实体类中的Clob类型替换为String,JPA会自动处理字符串与数据库Clob字段的转换,无需手动操作ClobProxy,代码更简洁易维护:
@Column(name="DES_PDFSETTING_URPST", columnDefinition = "CLOB") public String getDesPdfsettingUrpst() { return this.desPdfsettingUrpst; } public void setDesPdfsettingUrpst(String desPdfsettingUrpst) { this.desPdfsettingUrpst = desPdfsettingUrpst; }
更新代码直接传入字符串即可:
update.set("desPdfsettingUrpst", pdfSettings);
方案3:用CriteriaBuilder.coerce()强制转换类型
通过coerce()方法将ClobProxy实例强制转换为java.sql.Clob类型,满足Hibernate的类型校验要求:
Clob clobProxy = ClobProxy.generateProxy(pdfSettings); update.set("desPdfsettingUrpst", cb.coerce(clobProxy, Clob.class));
内容的提问来源于stack exchange,提问作者mahtab nematollahi
相关产品推荐
相关产品推荐

