Spring boot jpa查询无法更新字段

Posted

技术标签:

【中文标题】Spring boot jpa查询无法更新字段【英文标题】:Spring boot jpa query can't update field 【发布时间】:2021-10-18 13:43:39 【问题描述】:

我在这张表上有一个关于休眠的更新查询

class PackEntity 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String status;
    private String oldStatus;
    @ManyToOne
    @JoinColumn(name = "order_id")
    private OrderEntity order;
    ...

在 OrderEntity 上,当我有机器名称时,我与另一个表存在另一种关系。

在 JPA 存储库中,我有查询。基本上首先我按机器和状态搜索,然后我想更新旧状态以放置状态字段的当前值并在状态中放置新状态。就是这样:

@Transactional
@Modifying(clearAutomatically = true)
@Query("UPDATE PackEntity p " +
        "SET p.oldStatus= p.status, p.status = ?3 " +
        "WHERE p.id IN " +
        "     ( SELECT p2" +
        "       FROM PackEntity p2" +
        "       JOIN p2.order " +
        "       JOIN p2.order.machine" +
        "       WHERE p2.order.machine.name = ?1 AND p2.status = ?2)")
List<PackEntity > updateAllWithStatusByMachineNameAndStatus(String machineName, String status, String newStatus);

现在我遇到了这个错误 .QueryExecutionRequestException: Not supported for DML operations [UPDATE com.pxprox.entities.PackEntity with root cause ...

【问题讨论】:

问题可能是方法的返回类型,看这里:***.com/questions/44022076/… 您正在使用一种预期结果为 PackEntity 的方法进行更新。那是行不通的。此外,您的子选择是错误的,您选择的是整个实体,而您应该选择 p2.id @M.Deinum 你能举个例子吗 举个例子?您的方法应该返回 voidint 而不是 List&lt;PackEntitiy&gt; 并且如前所述,您的子选择也可能是错误的,返回一个 id 并且您也不需要其中的 JOIN。 @M.Deinum 由于WHERE p2.order.machine.name 的条件,我需要连接,否则会抛出错误。关于子查询,我选择SELECT p2",即List&lt;PackEntitiy&gt;。我唯一的问题是在我添加p.oldStatus= p.status, 之后它不起作用 【参考方案1】:

为什么不创建一个为您执行此操作的方法?初始化实体并更新所有内容,更改将在事务结束时自动刷新。你可以看看updating entity with spring-data-jpa

基本上应该是这样的:

@Autowired
private PackEntityRepository packEntityRepository;

public void updatePackEntity(PackEntity newPE) 
    PackEntity packEntity = packEntityRepository.findById(newPE.getId());
    packEntity.setOldStatus = packEntity.getStatus();
    packEntity.setStatus = newPE.getStatus();
    packEntityRepository.save(packEntity);

【讨论】:

这将是一个批量更新,所以我需要使用查询或本机查询进行更新?你能帮忙吗【参考方案2】:

方法的返回类型错误,查询也应该稍作调整。使用以下内容:

@Transactional
@Modifying(clearAutomatically = true)
@Query("UPDATE PackEntity p " +
        "SET p.oldStatus = p.status, p.status = ?3 " +
        "WHERE EXISTS " +
        "     ( SELECT 1" +
        "       FROM PackEntity p2" +
        "       JOIN p2.order o " +
        "       JOIN o.machine m" +
        "       WHERE m.name = ?1 AND p2.status = ?2 AND p2.id = p.id)")
void updateAllWithStatusByMachineNameAndStatus(String machineName, String status, String newStatus);

甚至更好

@Transactional
@Modifying(clearAutomatically = true)
@Query("UPDATE PackEntity p " +
        "SET p.oldStatus = p.status, p.status = ?3 " +
        "WHERE p.status = ?2 AND EXISTS " +
        "     ( SELECT 1" +
        "       FROM p.order o " +
        "       JOIN o.machine m" +
        "       WHERE m.name = ?1)")
void updateAllWithStatusByMachineNameAndStatus(String machineName, String status, String newStatus);

【讨论】:

以上是关于Spring boot jpa查询无法更新字段的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Spring Boot 更新现有实体

Spring Boot jpa 无法插入包含重音的字符串的行

Spring Boot + Spring Data JPA + 事务无法正常工作

如何通过 Spring Boot JPA 执行具有 INTERVAL 子句的本机 SQL 查询?

使用 Spring 数据 JPA 的 Spring Boot:无法提取 ResultSet

当加载 spring-boot 和 spring-data-jpa 时,Hibernate 无法加载 JPA 2.1 Converter