在Spring Boot 1.3.0应用程序中,我使用Spring Data JPA和Hibernate。
我有这种服务方法:
@Override
@Transactional(readOnly = false)
public BookDto updateBook(BookDto bookDto) {
BookId id = new BookId(bookDto.getId());
if (!exists(id)) {
throw new EntityNotFoundException("Unable to find a book with id " + bookDto.getId());
}
return convertToDto(bookRepository.save(bookDto.convertToBook()));
}
在我的实体中,我有一个@Version字段:
@Version
private long version;
(使用getter和setter)我也在我的DTO中有这个(在我的DTO上没有@Version注释)。
来自bookRepository.save()
来电的“预订”实体仍然有version = 0
,而不是预期的1
。当我在存储库中执行findAll
之后,版本会更新。这可能是什么原因?
答案 0 :(得分:2)
因为它是一个事务,所以在return语句之后发生提交。在这种情况下,在提交事务时,更改将保留在数据库中。由于您没有明确刷新,因此更改仅在提交后反映在数据库中。在提交操作之前,您将实体的当前状态映射到DTO。
解决方案1
如果您的spring存储库正在扩展JpaRepository,那么您可以执行以下操作。
@Override
@Transactional(readOnly = false)
public BookDto updateBook(BookDto bookDto) {
BookId id = new BookId(bookDto.getId());
if (!exists(id)) {
throw new EntityNotFoundException("Unable to find a book with id " + bookDto.getId());
}
return convertToDto(bookRepository.saveAndFlush(bookDto.convertToBook()));
}
解决方案2
没有显式刷新的另一种解决方案:在updateBook()方法之外移动实体到dto的转换。使用一些其他辅助函数将实体映射到dto。原因是因为如果没有显式刷新,实体在提交操作后与数据库同步。但是在提交事务之前,您将它们映射到DTO。因此,将实体移动到DTO映射到某个映射器类,或者在服务层中执行。
@Override
@Transactional(readOnly = false)
public BookEntity updateBook(BookDto bookDto) {
BookId id = new BookId(bookDto.getId());
if (!exists(id)) {
throw new EntityNotFoundException("Unable to find a book with id " + bookDto.getId());
}
return bookRepository.save(bookDto.convertToBook());
}
// call this method to map book entity to dto
public BookDTO mapToDTO(BookEntity){
return bookDTO;
}