Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何告诉Springdata存储库';如果某个实体不存在,是否使用s delete方法不引发异常?_Java_Spring_Spring Data - Fatal编程技术网

Java 如何告诉Springdata存储库';如果某个实体不存在,是否使用s delete方法不引发异常?

Java 如何告诉Springdata存储库';如果某个实体不存在,是否使用s delete方法不引发异常?,java,spring,spring-data,Java,Spring,Spring Data,我正在使用SpringData的存储库。如果我试图通过一个不存在或从未存在的ID删除一个实体,它会抛出一个异常。因为我不想在删除实体之前检查它是否存在,所以最好它能以静默方式失败。这将使它变得更容易,因为可观察的行为是相同的——在调用之后,实体不再存在。无论它是否被删除或从未存在,我都不在乎 是否有方法修改delete(EntityId)的默认行为,以便在实体不存在时不会引发异常 表示如果实体不存在,它将抛出异常。更新的答案(在否决投票后) 我最初的回答(如下)实际上是错误的:我对这个问题的理解

我正在使用SpringData的存储库。如果我试图通过一个不存在或从未存在的ID删除一个实体,它会抛出一个异常。因为我不想在删除实体之前检查它是否存在,所以最好它能以静默方式失败。这将使它变得更容易,因为可观察的行为是相同的——在调用之后,实体不再存在。无论它是否被删除或从未存在,我都不在乎

是否有方法修改
delete(EntityId)
的默认行为,以便在实体不存在时不会引发异常

表示如果实体不存在,它将抛出异常。

更新的答案(在否决投票后)

我最初的回答(如下)实际上是错误的:我对这个问题的理解也受到官方JavaDoc中缺少
EmptyResultDataAccessException
引用的影响(正如Adrian Baker在评论中所报告的)

因此,Yamashiro Rion可能会提出更好的解决方案

if (repository.existsById(entityId)) {
    repository.deleteById(entityId);
}
或者这个(没有
if
,但可能性能更差):


原始(错误)答案

JavaDocs说,如果提供的参数(id、entity、
Iterable
)为null,而实体不存在,则将抛出
IllegalArgumentException

如果需要避免出现
IllegalArgumentException
,可以实现一个检查
id!=空

public void customDelete(ID id) {
    if(id != null){
        this.delete(id);
    }
}
如果您不知道如何添加“Spring数据存储库的自定义实现”,请参阅覆盖该方法:

@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));
    }

需要更少代码的可行解决方案是向存储库接口添加一个新方法,如下所示:

// @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);`

-->要测试这是否可以与JPQL而不是本机SQL一起使用,以允许比默认id类型更复杂的id类型(int、long、String等)

我使用@SQLDelete注释来覆盖默认的Hibernate DELETE方法并抑制异常引发:

@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;
...
}
然后hibernate自动用MyTable对象的实际id替换prepared语句中的“?”,该id映射到表的SQL字段“my_id”


在这种情况下,如果表中的记录不存在,则不会引发异常,只会以静默方式删除0行,如在纯SQL删除查询中,使用
JpaRepository
可以轻松删除实体(如果存在)。在本例中,
PostsRepository
扩展了
JpaRepository

if (postsRepository.existsById(postId)) {
    postsRepository.deleteById(postId);
}

如果找不到实体,我使用bellow方法抛出有意义的异常

if (postsRepository.existsById(postId)) {
    throw new EntityNotFoundExceptionById("Invlaid Id was provided");
}

postsRepository.deleteById(postId);
EntityNotFoundExceptionById类

@ResponseStatus(HttpStatus.NOT_FOUND)
public class EntityNotFoundExceptionById extends RuntimeException {

    public EntityNotFoundExceptionById(String message) {
        super(message);
    }

}

如果你只需要用一个Id删除,你可以这样做

if(repsoitory.existsById(id)){ 
   repository.deleteById(id)
}
如果您有一个要删除的ID列表,那么您可以使用Java8

 List<Long> ids=new ArrayList<>();
  ids.stream().filter(id->repository.existsById(id))
              .forEach(id->repository.deleteById(id));
List id=new ArrayList();
id.stream().filter(id->repository.existsById(id))
.forEach(id->repository.deleteById(id));

在存储库中,您应使用返回类型
整数定义方法:

整数deleteMEntityById(长id);

如果要删除的实体不存在,如果该实体已被删除,您的方法将返回0或1。

很抱歉再次询问。如果我写我的customRepository,我还需要接口吗?或者我可以让它成为一个实现存储库接口的抽象类吗?@EhmKah是的,您需要添加一个带有自定义方法的接口,并在一个具体的类中实现它们。文件对此非常清楚。看一看,我看不出这个答案是如何针对一个不存在的实体的问题的?提供的ID参数可能是非null的,但数据存储中不存在这样的实体。这个答案是如何防止这种情况下出现异常的?尽管不幸的是javadoc中没有说明,但org.springframework.data.jpa.repository.support.SimpleParepository实现在实体不存在时抛出EmptyResultDataAccessException。这毫无意义。我无法理解为什么这是正确的答案。这似乎是更好的答案,不使用本机查询,不使用try-catch,而且非常简单。如果使用多个线程,它也可能引发异常(老实说,几乎所有系统都是多线程的)。在“if”语句之后,实体可能会被其他线程删除。此解决方案最终将抛出EmptyResultDataAccessException。不需要进行本机查询,JPQL可以执行批量删除。看起来这是唯一有效的答案,其余的有竞争条件。如果找不到id,则不应抛出not found exception,因为可能有一个作弊来检查这个ID是否存在于你的信息系统中。那不安全。你说的作弊是什么意思?existsById需要在Crudepository中实施。为什么这是一个欺骗?同意existsById来自CrudePository,但当我们使用它并抛出自己定义的EntityNotFoundExceptionById时,编程上是不安全的。
 List<Long> ids=new ArrayList<>();
  ids.stream().filter(id->repository.existsById(id))
              .forEach(id->repository.deleteById(id));