java - 在调用 @PreUpdate 之前 JPA 刷新到数据库
问题描述
为了创建卷影副本,我试图在执行保存之前捕获数据库中的实体数据。
EntityListener
我在我的 Spring 应用程序中实现了以下内容:
public class CmsListener {
public CmsListener() {
}
@PreUpdate
private void createShadow(CmsModel entity) {
EntityManager em = BeanUtility.getBean(EntityManager.class);
CmsModel p = em.find(entity.getClass(), entity.getId());
System.out.println(entity);
}
}
entity
确实包含要保存的实体对象,然后我使用另一个工具注入它EntityManager
,它工作正常 - 但由于某种原因,实体已经保存到数据库中。结果的输出是CmsModel p = em.find(...)
相同的数据,位于entity
.
为什么在调用 @PreUpdate 之前 JPA/hibernate 会保留更改?我怎样才能防止这种情况?
解决方案
我认为这是因为 em.find 实际上并没有查询数据库,而是从缓存中获取对象,所以它实际上获取了相同的对象实体引用(已经应用了更改)。
您可以检查数据库日志以获取获取 entity.id 数据的查询,以验证确实是这种情况,或者您可以在 createShadow() 中添加断点并在函数运行时查看实体的数据库条目调用以亲自查看更改是否已应用于当时的数据库。
要真正解决您的问题并获取卷影副本,您可以通过本机查询直接从数据库中获取对象。这是一个未经测试的示例:
public CmsModel fetchCmsModelDirectly(){
Query q = em.createNativeQuery("SELECT cm.id,cm.value_a,cm.value_b FROM CmsModel cm", CmsModel.class);
try{
return q.getSingleResult();
}catch(NoResultException e){
return null;
}
}
推荐阅读
- javascript - 在Javascript中将recordSet对象转换为JSON数组
- c# - 如何将 Blazor C# 应用程序连接到 Azure SQL 数据库?苹果系统
- python - 当有来自特定频道(热图)的更新时,如何打印消息?
- java - 带有子句 IN 列表的 AWS Amazon Redshift 驱动程序错误
- performance - .net core 2.1 迁移后的性能问题
- c# - 如何将寄存器移位为零?
- xamarin - 我可以在 Xamarin TabbedPage(iOS 和 Android)中设置选项卡文本颜色或图标以指示页面上的验证错误吗?
- node.js - 在命令文件中使用主文件中的变量,而不会与 discord.js 混淆
- android - 如何使用监视地理位置变化的地理位置组件?
- three.js - Draco 压缩后未对齐的 UV 坐标