Hibernate JPA无法在通过非主键(email、type)立即保存新记录(毫秒内)后获取新记录,但可以通过主键(id)获取新记录

eqoofvh9  于 2023-02-09  发布在  其他
关注(0)|答案(1)|浏览(137)

我的系统有一个 * patient * 实体,其中包含email(字符串)、type(整数)字段,这两个字段都是非主字段、非唯一字段和非空字段以及其他字段,当然还有主键ID。
保存新的患者实体后,当我通过jpa query * findById * 在数据库中搜索实体时,它运行良好,并获取几毫秒前刚刚保存的新实体。
但是,当我按电子邮件搜索新保存的实体并按jpa查询类型 * findByEmailAndTypeAndEmailIsNotNull * 时,它什么也不返回,但如果我在保存新实体1秒后运行完全相同的 * findByEmailAndTypeAndEmailIsNotNull * 查询,它将返回新保存的实体。
有人能诊断出这个问题吗?它甚至与JPA有关吗?还是与数据库本身有关?
编辑:

public synchronized Patient addPatient(PatientProfileDto patientProfileDto, Integer facilityId)
        throws ResourceAlreadyExistsException, EntityNotFoundException, ClientException {
    // some code

    performPatientCreationValidations(ownerDto, ownerDemographicDto.getNationality().getId(), Boolean.FALSE, Boolean.FALSE);

    // patient creation

    patientRepository.saveAndFlush(patient);

    // some code to link patient to other entities
}

private void performPatientCreationValidations(...params)
        throws ResourceAlreadyExistsException, ClientException {
    if (patientRepository.findByEmailAndTypeAndEmailIsNotNull(patientDto.getEmail(), PatientType.OWNER.getId()).isPresent()) {
        // throw error
    }
}

如果我连续点击API 5次,延迟可忽略,则会创建2个重复患者,但在最后3次API点击时,它会抛出错误。在收到第2次API点击时,它也应抛出错误。还应注意,患者的添加是同步函数,因此当一次API点击完成保存患者时,另一次API点击将获得函数n的锁定,继续。

sy5wg1nm

sy5wg1nm1#

保存新的患者实体后,当我通过jpa查询findById在数据库中搜索实体时,它运行得非常好
JpaRepository.findById()可以很好地工作,因为它从Hibernate的一级缓存中获取实体,而不是从数据库中获取实体,因为插入数据库通常被推迟到必要的时候,例如,直到会话被刷新。
因此,您必须使用JpaRepository.flush()手动刷新会话,或者使用JpaRepository.saveAndFlush()而不是JpaRepository.save(),或者在一个事务中执行操作,在这种情况下,您的请求共享一个会话,并且Hibernate将在获得针对同一实体的新查询后立即刷新其缓存。

相关问题