postgresql用spring data jpa更新jsonb字段

1. jsonb更新操作

1.1 更新某个属性(jsonb)中的某个元素的值。

https://stackoverflow.com/questions/26703476/how-to-perform-update-operations-on-columns-of-type-jsonb-in-postgres-9-4
比如说我们先插入一条数据:

CREATE TABLE test(id serial, data jsonb);
INSERT INTO test (data) values ('{"name": "my-name", "tags": ["tag1", "tag2"]}');

将data这个字段中name属性的值更新为my-other-name:

UPDATE test SET data = jsonb_set(data, '{name}', '"my-other-name"');

1.2 直接更新这个属性(jsonb)

我们假设表mytesttable中有一个sourcenames属性,是jsonb类型的。

1.2.1 按照正常的语句更新即可,只不过要用to_jsonb()函数把string转成jsonb格式。

但是用to_jsonb有一个问题:

....调用dao的test函数更新...
Map<String, Integer> map = new HashMap<>();
map.put("b", 2);
dao.test(new ObjectMapper().writeValueAsString(map)); //实现在下面

-----------------分割线----------------

...DAOImpl dao的实现...
@Transactional
@Modifying
@Query(value = "update mytesttable " +
        "set sourcenames = to_jsonb(:sourcenames) where tenantid='testTenant'", nativeQuery = true)
void test(@Param("sourcenames") String sourcenames);

这样写进去的内容是:{"b" : 2},带有反斜杠,这样的格式不是我们想要的

1.2.2 直接save整个entity

这样不管你是update还是insert,都不用自己去处理jsonb了,直接构造一个entity就行了。但是对于更新的场景,这样做效率会受影响。

1.2.3 用::jsonb

****用?符号传参****
@Transactional
@Modifying
@Query(value = "update mytesttable set " +
        "sourcenames = ?1::jsonb where tenantid='testTenant'", nativeQuery = true)
void test(String sourcenames);

***用@Param传参***
@Transactional
@Modifying
@Query(value = "update mytesttable set " +
        "sourcenames = :sourcenames::jsonb where tenantid='testTenant'", nativeQuery = true)
void test(@Param("sourcenames")String sourcenames);

上面这2中方法有一个重要的问题,就是JPA把::jsonb识别成了通过@Param传进来的参数了。这样他就会去函数的入参中找:jsonb,但是它又找不到,于是就报错:

Caused by: org.hibernate.QueryException: JPA-style positional param was not an integral ordinal
    at org.hibernate.engine.query.spi.ParameterParser.parse(ParameterParser.java:195)
    at org.hibernate.engine.query.spi.ParamLocationRecognizer.parseLocations(ParamLocationRecognizer.java:56)
    at org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.getParameterMetadata(NativeQueryInterpreterStandardImpl.java:30)
    at org.hibernate.engine.query.spi.QueryPlanCache.getSQLParameterMetadata(QueryPlanCache.java:128)
    at org.hibernate.internal.AbstractSharedSessionContract.getNativeQueryImplementor(AbstractSharedSessionContract.java:1000)

解决方案就是:用转义符!(\:\:jsonb)

@Query(value = "update mytesttable set " +
        "sourcenames = ?1\\:\\:jsonb where tenantid='testTenant'", nativeQuery = true)
void test3( String sourcenames);
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容