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);