【问题标题】:Spring Data repo not returning updated @version from save methodSpring Data repo 未从 save 方法返回更新的@version
【发布时间】:2016-03-29 23:35:15
【问题描述】:

在 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() 调用返回的“Book”实体仍然具有version = 0,而不是预期的1。当我之后在存储库上执行findAll 时,版本更新得很好。这可能是什么原因?

【问题讨论】:

    标签: spring hibernate jpa spring-data


    【解决方案1】:

    因为它是一个事务,所以提交是在返回语句之后发生的。在这种情况下,在提交事务时,更改会保留在数据库中。由于您没有显式刷新,因此更改仅在提交后才会反映在数据库中。在提交操作之前,您将实体的当前状态映射到 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

    另一种没有显式刷新的解决方案:将实体到 dto 的转换移到 updateBook() 方法之外。使用其他一些辅助函数将实体映射到 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;
    }
    

    【讨论】:

    • 此方法在我的BookService 中,我的BookController 使用它。您是说在我的服务中使用BookEntity 并在控制器中进行 DTO 转换会更好吗?
    • 没有。我不是那个意思。有不同的方法可以实现这一点。您可以创建另一个层,以便您的服务层与该层对话。为什么我们要创建这些附加层,因为 spring 在代理上工作,否则事务将无法工作。如果您不想要额外的课程,您可以使用flush。我只是给出了不同的解决方案。您可以选择最适合的。我建议不要在 Controller 拥有实体。
    • plz,如果对你有用,你能接受答案吗?
    • 我最终将转换放入我的控制器中,如下所示:baeldung.com/…
    猜你喜欢
    • 2020-03-26
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多