HQL中使用JSON_TRANSFORM更新JSON字段失败求助
解决方案
问题根源
HQL是Hibernate的跨数据库查询语言,它不支持Oracle专属的json_transform函数语法,所以直接写在HQL更新语句里会触发语法解析异常——哪怕这条语句在Oracle SQL Developer里能正常运行。
可行方案
1. 改用原生SQL执行更新操作
直接使用Hibernate的createNativeQuery方法执行Oracle原生SQL,绕过HQL的语法校验:
String updateSql = "update MY_DETAILS set details = json_transform(details, set '$.defaultValue' = :defaultValue0) where json_value(details, '$.defaultValue') = :defaultValue1"; Query query = entityManager.createNativeQuery(updateSql); query.setParameter("defaultValue0", 0); query.setParameter("defaultValue1", 1); query.executeUpdate();
注意表名要写数据库里的实际表名(Oracle默认表名大写),而非实体类名。
2. 封装JSON更新逻辑到数据库存储过程
如果需要复用这个更新逻辑,可以在Oracle中创建存储过程,再通过Hibernate调用:
CREATE OR REPLACE PROCEDURE reset_default_value(p_new_default_val NUMBER, p_old_default_val NUMBER) AS BEGIN UPDATE MY_DETAILS SET details = json_transform(details, set '$.defaultValue' = p_new_default_val) WHERE json_value(details, '$.defaultValue') = p_old_default_val; END; /
Java代码中调用存储过程:
StoredProcedureQuery spq = entityManager.createStoredProcedureQuery("reset_default_value"); spq.registerStoredProcedureParameter("p_new_default_val", Integer.class, ParameterMode.IN); spq.registerStoredProcedureParameter("p_old_default_val", Integer.class, ParameterMode.IN); spq.setParameter("p_new_default_val", 0); spq.setParameter("p_old_default_val", 1); spq.execute();
补充说明
- 你的查询语句能用HQL执行,是因为
json_value在部分Hibernate版本中被识别为兼容函数,但json_transform是Oracle 12cR2+的专属函数,HQL没有内置支持。 - 执行更新时务必开启事务,避免并发场景下出现多条记录默认值为1的情况,可通过行级锁或事务隔离级别控制并发。
内容的提问来源于stack exchange,提问作者Rachan R K
相关产品推荐
相关产品推荐

