使用JOOQ更新PostgreSQL的JSONB字段值报语法错误如何解决?
问题根因
你遇到的语法错误核心原因是:jOOQ 的 Plain SQL 模板语法中,{} 会被识别为参数占位标记,你直接将带大括号的JSON字符串写在field()方法的第一个参数中时,JSON的外层大括号被jOOQ解析为模板标记,导致最终生成的SQL丢失了JSON的外层结构和引号,触发PostgreSQL语法错误。
解决方案
方案1:转义模板大括号(仅适合临时硬编码场景)
在Plain SQL模板中,要输出字面量的{、}需要用双大括号{{、}}转义,修改后的代码如下:
DSL.using(connection).update(USER_SETTINGS) .set(USER_SETTINGS.SETTING_VALUE, field("{{\"filtersValue\":{{\"page\":0,\"size\":100}}, \"visibleCount\":100}}", JSONB.class)) .where(USER_SETTINGS.USER_ID.eq(98383L)) .execute();
方案2:使用DSL.val()绑定参数(更推荐,安全无转义问题)
直接将JSON字符串作为值绑定,jOOQ会自动处理类型转换,不需要处理转义,也避免SQL注入风险:
String jsonContent = "{\"filtersValue\":{\"page\":0,\"size\":100}, \"visibleCount\":100}"; DSL.using(connection).update(USER_SETTINGS) .set(USER_SETTINGS.SETTING_VALUE, DSL.val(jsonContent, JSONB.class)) .where(USER_SETTINGS.USER_ID.eq(98383L)) .execute();
方案3:Java对象序列化写入(适合复杂JSON场景,易维护)
如果JSON结构复杂,建议先定义对应的Java实体类,用JSON序列化工具(比如Jackson)转成字符串后再写入,避免手动拼接JSON出错:
// 定义配置实体类 public class FiltersValue { private Integer page; private Integer size; // 省略getter、setter } public class SettingValue { private FiltersValue filtersValue; private Integer visibleCount; // 省略getter、setter } // 序列化后写入 ObjectMapper objectMapper = new ObjectMapper(); FiltersValue filters = new FiltersValue(); filters.setPage(0); filters.setSize(100); SettingValue setting = new SettingValue(); setting.setFiltersValue(filters); setting.setVisibleCount(100); String jsonStr = objectMapper.writeValueAsString(setting); DSL.using(connection).update(USER_SETTINGS) .set(USER_SETTINGS.SETTING_VALUE, DSL.val(jsonStr, JSONB.class)) .where(USER_SETTINGS.USER_ID.eq(98383L)) .execute();
内容的提问来源于stack exchange,提问作者Oleksii Hlovatskyi
相关产品推荐
相关产品推荐

