首页 > 解决方案 > CrudRepository save() 抛出“行已被另一个事务更新或删除”

问题描述

在使用 JpaRepository 对我的数据库进行更新事务期间出现错误。我看到这里有很多关于这个错误的问题,但提到的解决方案似乎都没有解决我的问题。这是我的主要方法:

 public View update(Long productCode, Long customerCode, UpdateForm form) {

        var entityToUpdate = repository.findByProductCodeAndCustomerCode(productCode, customerCode);

        var updatedObject = new Builder(entityToUpdate).build(form);
        var savedObject = repository.save(updatedObject); //error thrown here

        return converter.convertToView(savedObject);
    }

这是上面出现的 Builder 类实现:

    public class Builder {

    private final Purchase entityToUpdate;

    public Builder(Optional<Purchase> entityToUpdate) {
        this.entityToUpdate = entityToUpdate.isPresent() ? entityToUpdate.get() : null;
    }

    public Purchase build(PurchaseUpdateForm form) {

        this.entityToUpdate.setDiscount(form.getDiscount());
        this.entityToUpdate.getId().setPurchaseBoxQuantity(form.getPurchaseBoxQuantity());

        return entityToUpdate;
    }
}

我尝试@Transactionalupdate()andbuild()方法中添加一个,但错误仍然存​​在。我也尝试使用saveAndFlush但没有任何改变。完整的日志消息:

Optimistic locking failed; nested exception is caused by: org.hibernate.StaleObjectStateException: 
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): 
[PurchasePK@bb7039e8]

# 附加信息 - 域

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "TB_PURCHASE")
public class Purchase {
    
    @EmbeddedId
    private PurchasePK id;
    
    @NotNull
    @Column(name = "DISCOUNT")
    private BigDecimal discount;
}

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = { "product", "purchaseBoxQuantity" })
@Embeddable
public class PurchasePK {
    
    @NotNull
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "CD_PRODUCT")
    @JoinColumn(name = "CD_CUSTOMER")
    private Product product;
    
    @NotNull
    @Column(name = "QT_BOXES")
    private Long purchaseBoxQuantity;
}

标签: javaspringoraclespring-data-jpa

解决方案


如果没有完整的源代码,我只能猜测问题出在您的嵌入式 id 上,特别是我猜它必须与

@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)

我建议您将以下属性添加到您的应用程序属性文件中

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

这样您就可以检查您的实体的 id 可能如何以您没想到的方式更改。


推荐阅读