JpaRepository 缓存新创建的对象。怎么刷新呢?

2024-04-12

我有一个 JpaRepository 在 Spring MVC 应用程序中保存新创建的实体。这个实体看起来像这样(非常简单):

@Entity
public class Translation {

    .....

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private Version version;

    ....

}

和版本实体:

@Entity
public class Version {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private long id;

    @Column(name = "name")
    private String name;

    @Column(name = "version_code")
    private long code;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "version", cascade = {CascadeType.ALL}, orphanRemoval = true)
    private Set<Translation> translations;

}

我创建一个像这样的翻译对象

            TranslationDTO t = new TranslationDTO();
            t.setText(translationText);
            ClientVersionDTO version = new ClientVersionDTO();
            version.setId(11);
            t.setVersion(version);

其中 11 是数据库中从一开始就存在的版本。请注意,我没有设置值name and codeClientVersionDTO 的。

然后我有一个保留新对象的服务(我使用dozer将 DTO 转换为实体的库)

@Service
@Transactional
public class TranslationsServiceImpl implements TranslationsService {
    @Override
    public Long create(TranslationDTO translationDTO) {
        Translation translation = translationsConverter.unconvert(translationDTO);
        Translation t = translationRepository.saveAndFlush(translation);

        Translation t2 = translationRepository.findOne(t.getId());

        // !!!! t2.getVersion() returns version where no values are set to 'code' and 'name'

        return t2.getId();
    }
}

请注意我的评论“t2.getVersion() 返回没有值设置为‘代码’和‘名称’的版本” - 我期望这样当我从数据库中获取数据时,我会得到一个Version直接从数据库中获取对象code and name值设定。然而它们还没有设置。所以基本上我得到的是t2.getVersion()对象与输入参数中的对象相同translationDTO.getVersion()。我怎样才能让他们重新失效Version object?

UPDATE尝试将 @Transactional 移至 JpaRepository,但结果仍然相同。


如果您使用 Hibernate,这就是预期的结果。你打电话时translationRepository.saveAndFlush(translation) and translationRepository.findOne(t.getId())他们一个接一个地访问同一个 Hibernate 会话,该会话维护其处理过的所有对象的缓存。因此,第二次调用只是返回传递给第一次调用的对象。这两行中没有任何内容会迫使 Hibernate 触发SELECT在数据库中查询Version entity.

现在,JPA 规范确实有一个refresh方法上的EntityManager界面。不幸的是,Spring Data JPA 没有使用其公开此方法JpaRepository界面。如果这个方法可用,你可以这样做t = translationRepository.saveAndFlush(translation)进而versionRepository.refresh(t.getVersion())强制 JPA 提供程序将版本实体与数据库同步。

实现这个方法并不困难。只需延长SimpleJpaRepository来自 Spring Data JPA 的类并自己实现该方法。详情请参阅向所有 Spring Data JPA 存储库添加自定义行为 http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-behaviour-for-all-repositories.

另一种方法是将版本实体加载为versionRepository.findOne(version.getId())在将其设置为翻译之前。由于您可以在代码中硬编码版本 ID,因此您的版本似乎是静态的。因此,您可以标记您的Version实体作为@Immutable and @Cacheable(前者是 Hibernate 特定的注释)。那样,versionRepository.findOne(version.getId())每次调用时不应访问数据库。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JpaRepository 缓存新创建的对象。怎么刷新呢? 的相关文章

随机推荐