在JPA中按对象的ID和版本删除对象

Ale*_*lex 4 spring hibernate jpa spring-mvc

我正在学习JPA,并且试图在Spring MVC Web应用程序中使用它。我需要实现一种删除对象/记录的方法。当前,我具有以下方法的实现:

@Transactional
public void deleteProduct(int productId, int productVersion) {

    Product product = entityManager.find(Product.class, productId);
    product.setVersion(productVersion);
    entityManager.remove(product);
}
Run Code Online (Sandbox Code Playgroud)

productVersion用于乐观锁定。它是来自Web GUI的对象/记录的旧版本。

此方法删除数据库中的记录,但是当数据库中的记录版本不匹配时,它不会引发任何异常productVersion。(我在删除对象方面只有一个问题:用来更新记录时entityManager.merge(product),出现消息异常Row was updated or deleted by another transaction)。

Hibernate生成以下SQL查询:delete from Product where id=? and version=?,即尝试检查该version字段。

我究竟做错了什么?

另外,通过ID删除对象是否正确?我担心我的方法生成了两个SQL查询:SELECTfor entityManager.find()DELETEfor entityManager.remove()。有没有删除对象/记录的最佳方法?

产品类别

@Entity
public class Product {

    @Id
    @GeneratedValue
    protected int id;

    protected String name;

    protected BigDecimal price;

    @Version
    protected int version;

    // getters and setters
}
Run Code Online (Sandbox Code Playgroud)

Var*_*nis 6

一种方法是在一个查询中手动执行此操作,如下所示:

@Transactional
public void deleteProduct(int productId, int productVersion) {
   int isSuccessful = entityManager.createQuery("delete from Product p where p.productVersion=:productVersion and p.id=:id")
            .setParameter("id", productId)
            .setParameter("productVersion", productVersion)
            .executeUpdate();
    if (isSuccessful == 0) {
        throw new OptimisticLockException(" product modified concurrently");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案的另一个问题是它不执行级联。在很多情况下,这个解决方案是不够的。我想实现此方法的通用版本(在 Spring Data JPA 中),最终得到:查找、手动检查版本并删除。或者,合并+删除可能有效,但我没有检查。 (2认同)