当前位置: 首页 > 面试题库 >

JpaRepository缓存新创建的对象。如何刷新呢?

闽焕
2023-03-14
问题内容

我有一个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是从一开始就已经存在于数据库中的版本。请注意,我没有为ClientVersionDTO 设置namecode的值。

然后,我有一个持久化新对象的服务(我使用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()返回没有将任何值设置为’code’和’name’的版本”-我期望如此,这样当我从数据库中获取数据时,我将从数据库中获取一个Version对象与codename设置的值。但是,它们尚未设置。因此,基本上,我作为t2.getVersion()对象得到的就是与输入自变量相同的对象translationDTO.getVersion()。他们如何重新使Version对象无效?

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


问题答案:

如果您使用的是Hibernate,则这是预期的结果。当你打电话translationRepository.saveAndFlush(translation),并translationRepository.findOne(t.getId())一前一后,他们打它保持的所有对象,它已经在工作的高速缓存中的同一个Hibernate
Session。因此,第二个调用只是返回传递给第一个对象的对象。这两行中没有任何内容会迫使Hibernate
SELECT在数据库上为该Version实体触发查询。

现在,JPA规范refreshEntityManager接口上确实有一个方法。不幸的是,Spring Data
JPA没有使用其JpaRepository接口公开此方法。如果可以使用此方法,则可以完成该操作t = translationRepository.saveAndFlush(translation),然后versionRepository.refresh(t.getVersion())强制JPA提供程序将版本实体与数据库同步。

实现此方法并不困难。只需SimpleJpaRepository从Spring Data JPA
扩展类并自己实现该方法即可。有关详细信息,请参阅向所有Spring Data
JPA存储库添加自定义行为。

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



 类似资料:
  • 我使用JPA(Eclipse Link 2.5)进行持久性。我的Web应用程序包含AJAX页面更新。保存帖子时,发布的内容会在不刷新浏览器的情况下显示。该帖子具有使用OneTo多关系与之关联的标签。这些标签应该在保存后也会显示出来。但是,由于启用了缓存,我无法获取标签。 这是我的代码: 我怎样才能让事情运转起来?如何刷新一个实体及其所有关联的实体?谢了。

  • 既然有一个,那么当使用时,有没有办法刷新更新的实体? 我试图按批处理更新实体。 真的会有很大的帮助! 非常感谢。

  • 本文向大家介绍如何刷新浏览器的应用缓存?相关面试题,主要包含被问及如何刷新浏览器的应用缓存?时的应答技巧和注意事项,需要的朋友参考一下 按F5或浏览器刷新按钮 浏览器会在请求中附加必要的缓存协商,但不允许浏览器直接使用本地缓存,它能够让 Last-Modified、ETag发挥效果,但是对Expires无效。 按Ctrl+F5或按Ctrl并点击刷新按钮 这种方式就是强制刷新,总会发起一个全新的请求

  • 问题内容: 线程1:正在执行此循环 线程2将运行错误设置为假如果运行是易失性变量,则线程1退出循环并显示“完成”。 我的问题是,如果运行不是易失的,那么Thread1何时从主内存中读取运行变量? 注意:我很了解同步和volatile变量之间的关系,但是即使运行不是volatile或同步的,线程1也会停止。所以我的问题是,鉴于没有同步或没有波动,线程1什么时候决定从主存储器读取数据 问题答案: 这在

  • 问题内容: 在log4j中,当使用具有BufferedIO = true和BufferSize = xxx属性(即启用了缓冲)的FileAppender时,我希望能够在正常关闭过程中刷新日志。有关如何执行此操作的任何想法? 问题答案:

  • 问题内容: 我有一个简单的User $ resource,它使用默认的$ http缓存实现,如下所示: 这非常好用,即我的服务器在应用程序中仅被调用一次,然后从缓存中获取值。 但是我需要在执行某些操作后从服务器刷新值。有没有简单的方法可以做到这一点? 谢谢。 问题答案: 保留布尔值并获取缓存: 然后,您可以像使用所提供的任何其他缓存一样控制它,这是下面提供的用法实例: