通过确保实体存在来更新实体的最佳方法是在 Spring Data JPA 中组合 getOne() 和 save() 吗?



我知道有几种方法可以用来更新现有实体。我将在下面提到两种方式。我需要澄清我对这两种方法的看法是否正确。最终目标是通过确保主键在更新之前有效,找到更新实体的最佳方法。因此,请随意陈述任何其他机制。

方法1:

  • 首先借助getOne()方法获取与更新实体相关的代理对象
  • 然后将需要由setter更新的字段设置为该代理对象
  • 使用save方法更新实体。在这里,我在保存之前使用getOne()方法,以确保我正在更新一个存在实体。否则,据我所知,如果实体的主键不是自动生成的字段,则插入save()方法的任何新主键都将在数据库中创建新实体。因此,如果插入的id不是现有id,那么通过遵循getOne()方法,我可以在save()方法调用的末尾出现EntityNotFound异常。因此,基本上按照这种方式,我可以省略数据库命中,该数据库命中通常会触发find(),在保存实体之前,给定的id已经存在。根据我的意见,这是通过确保给定的id始终存在来更新给定实体的最佳方式。问题是我以前在任何教程或网站上都没有看到这种方法。这是自己实现的。因此,我需要知道,与方法二相比,我们遵循这种机制是否有任何缺点
try {
CustomerCategory customerCategory = customerCategoryRepository.getOne(customerCategoryRequestDto.getCode());

customerCategory.setStatus(customerCategoryRequestDto.getStatus());

CustomerCategory savedCustomerCategory = customerCategoryRepository.save(customerCategory);
CustomerCategoryResponseDto customerCategoryResponseDto = modelMapper.map(savedCustomerCategory, CustomerCategoryResponseDto.class);
return customerCategoryResponseDto;
} catch (EntityNotFoundException e) {
throw new EntityNotFoundException(ExceptionMessage.MSG_ENTITY_NOT_FOUND);
}

方法2:

  • 首先查看给定的id是否存在于数据库中。否则,通知最终用户数据库中不存在给定的id。

  • 然后执行更新。在这里,我使用一个查询来更新实体。但这可以很容易地实现,方法是为上一个find()方法调用中找到的实体设置必要的字段,并调用save()方法。但我看到的问题是,我们需要一个额外的查询来确保给定的id是有效的。所以我认为这肯定会降低数据库的性能。但在大多数网站和教程中,大多数作者都遵循这种机制。我没有看到任何实际的用例,也没有看到我们需要这个机制而不是第一个。

Optional<CustomerCategory> searchedCustomerCategory = customerCategoryRepository.findById(customerCategoryRequestDto.getCode());
if (!searchedDbpCustomerCategory.isPresent()) {
throw new EntityNotFoundException(ExceptionMessage.MSG_ENTITY_NOT_FOUND);
}
customerCategoryRepository.updateCustomerCategory(CustomerCategoryStatus.DELETED.toString(), customerCategoryRequestDto.getCode());

实际上,有案例和案例。

当你只需要一个推荐人(例如维持关系(时,请使用JpaRepository#getOne(ID id)

当您需要更新实体时,请使用CrudRepository#findById(ID id)

但为什么

注意这样做:

Entity ref = repo.getOne(1l);
ref.setAttribute("value");

与此只有一个区别:

Entity entity = repo.findById(1l);
entity.setAttribute("value");

不同之处在于加载操作是getOne中的LazyfindById中的Eager

但是,当您需要更新实体中的列时,不会有任何性能提升。

当您在引用上调用setter或getter时,持久性提供程序确实会命中数据库,以便引入数据。这就是懒惰负载的含义——只在你需要的时候加载。通过调用setter,您确实需要数据,然后持久性提供程序将对数据库执行选择。

因此,当您的目标是更新实体时,使用getOne而不是findById并没有真正的好处。

此外,请注意,getOne已被弃用,取而代之的是getById,后者的作用完全相同。

最新更新