Java Crudepository.exists方法中的DataIntegrityViolationException

Java Crudepository.exists方法中的DataIntegrityViolationException,java,hibernate,spring-data,unique-constraint,Java,Hibernate,Spring Data,Unique Constraint,在我的服务中,在调用MyCrudepository.saveAndFlush处理并发持久(插入)请求时,已处理了DataIntegrityViolationException。它有效,我可以捕捉到异常。在此之后,我更愿意确定异常是否正是因为实体已经存在,而不是因为任何其他可能的未知问题。因此,我调用mycrudepository.exists(entity.getId()),但再次抛出DataIntegrityViolationException。 以下是我的简单代码: private void

在我的服务中,在调用MyCrudepository.saveAndFlush处理并发持久(插入)请求时,已处理了
DataIntegrityViolationException
。它有效,我可以捕捉到异常。在此之后,我更愿意确定异常是否正是因为实体已经存在,而不是因为任何其他可能的未知问题。因此,我调用
mycrudepository.exists(entity.getId())
,但再次抛出
DataIntegrityViolationException
。 以下是我的简单代码:

private void save(final Employee entity) throws MyAppException {
    try{
        this.myCrudRepository.saveAndFlush(entity);
    }catch (org.springframework.dao.DataIntegrityViolationException e){
        // check if the error is really because the entity already exists
        // entity.getId() is already generated before any save. it's like National ID
        boolean exists = this.myCrudRepository.exists(entity.getId()); // DataIntegrityViolationException is thrown here again!
        if (exists)
            throw new MyAppException(HttpStatus.CONFLICT, "Entity already exists.");
        else
            throw e;
    }
}
但是如果我使用
findOne
而不是
exists
,它就可以正常工作。这有点奇怪,但当然有一个技术原因,那就是我没有能力做出猜测


有什么想法吗?提前感谢。

问题是当您使用事务方法时,在该方法返回后,事务将自动提交,hibernate将把异常打包到另一个异常中。实际上,当事务提交时会发生异常,此时您已经退出了该方法。要从方法内部捕获异常,只需在
this.mycrudepository.saveAndFlush(entity)之后使用
em.flush()

谢谢您的回复,但实际上,我认为
exists
方法是按照默认的刷新策略,在获取数据之前尝试刷新未保存的更改(更准确、更可靠)。这就是调用
exists
方法时再次抛出相同异常的原因。因此,
em.clear()
在这里比
em.flush()
更有意义。但我不确定这基本上是否是一个好的实践。我在这里看到的基本情况是,除非您使用
em.flush()
,否则在您的方法中不可能导致任何异常。因此,如果使用
em.flush()
,则会抛出
DataIntegrityViolationException
,因为它会立即尝试执行数据库保存操作,并且只有在找到重复的行时才会抛出。没错
mycrudepository.exists
方法在内部调用
flush
方法(正如我在Hibernate堆栈跟踪中所看到的),因此您提到的一切都在发生。它面对数据库中的现有记录,并再次抛出
DataIntegrityViolationException
异常。