Spring Data repo没有从save方法返回更新的@version

时间:2015-12-23 13:57:42

标签: spring hibernate jpa spring-data

在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之后,版本会更新。这可能是什么原因?

1 个答案:

答案 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;
}