Java JpaRepository缓存新创建的对象。如何刷新它?
我在SpringMVC应用程序中有一个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
@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();
}
}