Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JpaRepository缓存新创建的对象。如何刷新它?_Java_Jpa_Spring Data Jpa - Fatal编程技术网

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

Java JpaRepository缓存新创建的对象。如何刷新它?,java,jpa,spring-data-jpa,Java,Jpa,Spring Data Jpa,我在SpringMVC应用程序中有一个JpaRepository持久化新创建的实体。此实体如下所示(非常简化): 和版本实体: @Entity public class Version { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private long id; @Column(name = "name") private String n

我在SpringMVC应用程序中有一个JpaRepository持久化新创建的实体。此实体如下所示(非常简化):

和版本实体:

@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;

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

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

请注意我的注释“t2.getVersion()返回的版本中没有将值设置为'code'和'name'”——我希望这样,当我从数据库中获取数据时,我将从数据库中获得一个设置了
code
name
值的
version
对象。然而,它们并没有被设定。因此,基本上我得到的
t2.getVersion()
对象与输入参数
translationDTO.getVersion()
中的对象相同。他们如何使
版本
对象重新失效


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

如果您使用的是Hibernate,这是预期的结果。当您依次调用
translationRepository.saveAndFlush(translation)
translationRepository.findOne(t.getId())
时,它们会进入同一个Hibernate会话,该会话维护它所处理的所有对象的缓存。因此,第二个调用只返回传递给第一个调用的对象。这两行中没有任何内容会迫使Hibernate在数据库中为
Version
实体启动
SELECT
查询

现在,JPA规范在
EntityManager
界面上有一个
refresh
方法。不幸的是,Spring数据JPA没有使用其
JpaRepository
接口公开此方法。如果此方法可用,您可以先执行
t=translationRepository.saveAndFlush(translation)
,然后执行
versionRepository.refresh(t.getVersion())
,以强制JPA提供程序将版本实体与数据库同步

实现这种方法并不困难。只需从Spring数据JPA扩展
SimpleParepository
类,并自己实现该方法。有关详细信息,请参阅


另一种方法是在转换上设置版本实体之前,将其加载为
versionRepository.findOne(version.getId())
。因为您可以在代码中硬编码版本id,所以您的版本看起来是静态的。因此,您可以将
版本
实体标记为
@不可变
@可缓存
(前者是特定于Hibernate的注释)。这样,
versionRepository.findOne(version.getId())
就不应该在每次调用数据库时都命中它。

您可能是指“Spring MVC”吗?这是因为你写了“Sprint MVC”是的,谢谢。修改了输入错误。尝试将@Transactional移动到存储库进行测试Benjamin.d,只是尝试了一下,但没有成功。找到更好的解决方案了吗?我有一个类似的问题:谢谢,事实上,我也得出了结论,并使用了第二种方法。顺便说一句,这个版本并没有被编码,只是为了简单起见。
@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);
@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();
    }
}