I am learning JPA, and I am trying to use it in a Spring MVC web app. I need to implement a method that deletes an object/record. Currently, I have the following implementation of the method:
@Transactional
public void deleteProduct(int productId, int productVersion) {
Product product = entityManager.find(Product.class, productId);
product.setVersion(productVersion);
entityManager.remove(product);
}
productVersion
is used for optimistic locking. It is the old version of the object/record that comes from the web GUI.
This method deletes the record in the DB, but it does not throw any exception when the version of the record in the DB does not match productVersion
. (I only have a problem with deleting objects: when I update a record with entityManager.merge(product)
, I get an exception with the message: Row was updated or deleted by another transaction
.)
Hibernate generates the following SQL query: delete from Product where id=? and version=?
, i.e. it tries to check the version
field.
What am I doing wrong?
Also, is it a correct approach to removing an object by its id? I am concerned that my method generated two SQL queries: a SELECT
for entityManager.find()
, and a DELETE
for entityManager.remove()
. Is there a more optimal way to delete an object/record?
Product class
@Entity
public class Product {
@Id
@GeneratedValue
protected int id;
protected String name;
protected BigDecimal price;
@Version
protected int version;
// getters and setters
}
One way is to do it manually in one query as follows:
@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");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With