我知道有几种方法可以用来更新现有实体。我将在下面提到两种方式。我需要澄清我对这两种方法的看法是否正确。最终目标是通过确保主键在更新之前有效,找到更新实体的最佳方法。因此,请随意陈述任何其他机制。
方法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
中的Lazy
和findById
中的Eager
。
但是,当您需要更新实体中的列时,不会有任何性能提升。
当您在引用上调用setter或getter时,持久性提供程序确实会命中数据库,以便引入数据。这就是懒惰负载的含义——只在你需要的时候加载。通过调用setter,您确实需要数据,然后持久性提供程序将对数据库执行选择。
因此,当您的目标是更新实体时,使用getOne
而不是findById
并没有真正的好处。
此外,请注意,getOne
已被弃用,取而代之的是getById
,后者的作用完全相同。