如何使用 Spring Data JPA 查询更新 PostgreSQL 中的 JSONB 列

Shi*_*tta 5 java postgresql jpa spring-data-jpa jsonb

我有以下控制器

@RequestMapping(value = "/update/{tableId}", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE,
            consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity updateItemQty (@PathVariable Long tableId, @RequestBody AddItemsRequestBody requestBody,
                                              HttpServletRequest request){
        try {
            String addedBy = getUserName(request);
            Float ItemQuantity = requestBody.getItemQuantity();
            LocalDateTime dateTimeAdded = LocalDateTime.now();
            String subId = requestBody.getItemSubId();
            ArrayList<ItemAdditionDetails> updatedAdditionDetails = new ArrayList<>();

        ItemAdditionDetails newItemAdditionDetails = new ItemAdditionDetails();
        newItemAdditionDetails.setIncreamentCount(ItemQuantity);
        newItemAdditionDetails.setAddedDateTime(dateTimeAdded);
        newItemAdditionDetails.setAddedBy(addedBy);

        updatedAdditionDetails.add(newItemAdditionDetails);

// Here i am fetching a JSON-B column that returns an array of json objects from Postgress DB  
     ItemInventoryService.findByItemSubId(subId).getItemsInventoryAdditionDetails().forEach((el) -> {
                updatedAdditionDetails.add(el);
            });

        itemInventoryService.updateItemsAdditionDetails(subId,updatedAdditionDetails);

        return new ResponseEntity("Updated", HttpStatus.CREATED);
    }catch (Exception ex){
        return new ResponseEntity(ex, HttpStatus.INTERNAL_SERVER_ERROR);
    }

}
Run Code Online (Sandbox Code Playgroud)

如果我删除/评论

ItemInventoryService.findByItemSubId(subId).getItemsInventoryAdditionDetails().forEach((el) -> {
                updatedAdditionDetails.add(el);
            });
Run Code Online (Sandbox Code Playgroud)

也就是说,我不将获取的结果添加到新的updatedAdditionDetails(类型为ArrayList)中,数据库更新成功否则我会收到以下错误:

错误:列“itemsinventory_addtion_details”的类型为 jsonb,但表达式的类型为记录\n 提示:您需要重写或转换表达式。\n 位置

在我的存储库中我有以下查询

@Transactional
    @Modifying
    @Query(value = "UPDATE items_inventory  SET itemsinventory_addtion_details = :updatedAdditionDetails WHERE item_subid = :subId", nativeQuery = true)
    Integer updateItemsAdditionDetails(@Param("subId") String subId, @Param("updatedAdditionDetails") List<ItemAdditionDetails> updatedAdditionDetails);
Run Code Online (Sandbox Code Playgroud)

我已经尝试过JPA方式如下:

 @Query(value = "UPDATE ItemsInventory items  SET items.itemsInventoryAdditionDetails = :updatedAdditionDetails WHERE items.itemSubId = :subId")
Run Code Online (Sandbox Code Playgroud)

不幸的是,这也带来了同样的错误。非常感谢对此的任何帮助。提前致谢。

Vla*_*cea 5

错误原因

PostgreSQL 错误如下所示:

错误:列“itemsinventory_addtion_details”的类型为 jsonb,但表达式的类型为记录\n 提示:您需要重写或转换表达式。\n 位置

导致此错误的原因是List这样传递的:

UPDATE
    ItemsInventory items
SET
    items.itemsInventoryAdditionDetails = (?, ?, ?, .., ?)
WHERE
    items.itemSubId = ?
Run Code Online (Sandbox Code Playgroud)

默认情况下,使用 Hibernate 的 Spring Data JPA 不知道如何处理 JSON 类型。因此,您需要使用自定义 Hibernate 类型,例如Hibernate TypesJsonBinaryType项目提供的类型。

Maven 依赖

首先,您需要添加 Hibernate Types 依赖项:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

hibernate-types.versionMaven 属性设置为最新版本后,将从 Maven Central 下载依赖项。

明确设置休眠类型

您将无法使用 Spring@Query注释,因为您无法显式设置 Hibernate 类型。

因此,您需要使用以下方法添加自定义 Spring Data JPA Repository 实现:

public int updateItemsAdditionDetails(
    String subId, 
    List<ItemAdditionDetails> updatedAdditionDetails) {
    return entityManager.createNativeQuery(
        "UPDATE items_inventory  SET itemsinventory_addtion_details = :updatedAdditionDetails WHERE item_subid = :subId")
    .unwrap(NativeQuery.class)
    .setParameter("updatedAdditionDetails", updatedAdditionDetails, JsonBinaryType.INSTANCE)
    .setParameter("subId", subId)
    .executeUpdate();
}
Run Code Online (Sandbox Code Playgroud)

就是这样!