问题
I am using SpringData's repository. If I try to delete an entity via an ID which does not exist or never existed it throws an exception. Since I do not want to check whether the entity exists before I delete it, it would be nice that it would fail silently. It would make it easier because the observable behavior is the same - after the call the entity does not exists anymore. Whether it has been deleted or never existed, I do not care.
Is there a way to modify default behavior of delete(EntityId)
so it won't throw an exception, if entity does not exsist?
Documentation of SpringData's delete says that it will throw an exception if an entity does not exist.
回答1:
Updated Answer (after downvotes)
My original answer (below) is actually wrong: my understanding of the question was influenced also by the missing reference to the EmptyResultDataAccessException
in the official JavaDoc (as reported by Adrian Baker in his comment).
So a better solution to this issue could be the one suggested by Yamashiro Rion
if (repository.existsById(entityId)) {
repository.deleteById(entityId);
}
or this one (without the if
, but probably worse performing):
repository.findById(entityId)
.map(repository::delete)
Original Answer
JavaDocs says that an IllegalArgumentException
will be thrown if the provided argument (id, entity, Iterable<T>
) is null and not if entity does not exsits.
If you need to avoid the IllegalArgumentException
you could implement a custom delete method that checks id != null
:
public void customDelete(ID id) {
if(id != null){
this.delete(id);
}
}
Take a look to this docs section if you don't know how to add "Custom implementations for Spring Data repositories"
回答2:
A viable solution that requires less code is to add a new method to the repository interface like this:
// @Modifying is necessary depending on your version of Spring
@Modifying
@Query(nativeQuery=true, value="DELETE FROM MY_TABLE WHERE ID = ?1")
public void deleteById(IdPrimitiveType id);`
--> to be tested if this can used with JPQL instead of native SQL to allow more complex id types than the default ones (int, long, String, ...)
回答3:
With JpaRepository
you can easily delete an entity if it exists. In this example PostsRepository
extends JpaRepository
:
if (postsRepository.existsById(postId)) {
postsRepository.deleteById(postId);
}
回答4:
Override the method :
@Transactional
@Override
public void delete(ID id) {
T entity = findOne(id);
if (entity == null) {
//do something instead of throwing exception ex:
//syso entity does not exist ; return;
}
em.remove(em.merge(entity));
}
回答5:
I used @SQLDelete annotation to override default Hibernate DELETE method and to suppress Exception throwing:
@javax.persistence.Entity
@Table(name = "mytable")
@Proxy(lazy = false)
@SQLDelete(
sql =
"DELETE FROM mytable " +
"WHERE my_id = ?"
)
public class MyTable {
@javax.persistence.Column(name = "my_id", nullable = false)
@Id
private Long id;
...
}
then hibernate automatically substitutes the '?' in prepared statement with actual id of MyTable object, which is mapped to SQL field 'my_id' of table
In this case no exception will be thrown if the record in table does not exist, only silently deletes 0 rows, as in plain SQL DELETE query
回答6:
I used bellow method to throw meaningful exception if the entity was not found.
if (postsRepository.existsById(postId)) {
throw new EntityNotFoundExceptionById("Invlaid Id was provided");
}
postsRepository.deleteById(postId);
EntityNotFoundExceptionById Class
@ResponseStatus(HttpStatus.NOT_FOUND)
public class EntityNotFoundExceptionById extends RuntimeException {
public EntityNotFoundExceptionById(String message) {
super(message);
}
}
来源:https://stackoverflow.com/questions/38785622/how-to-i-tell-a-springdata-repositorys-delete-method-to-not-throw-an-exception