如何访问从 Hibernate AbstractEvents 和 EventListeners 调用 repository.save(entity) 时使用的原始实体?
Posted
技术标签:
【中文标题】如何访问从 Hibernate AbstractEvents 和 EventListeners 调用 repository.save(entity) 时使用的原始实体?【英文标题】:How to access the original Entity used when repository.save(entity) is invoked from Hibernate AbstractEvents and EventListeners? 【发布时间】:2021-01-14 16:24:46 【问题描述】:我正在使用 JPA/Hibernate/Spring 并有一个简单的 JPA 实体模型,如下所示:
@Entity
@Table(name = "record")
public class Record extends BaseEntity
//...
@OneToMany(mappedBy = "record", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Document> documents;
@Entity
@Table(name = "document")
public class Document extends BaseEntity
//...
@ManyToOne
@JoinColumn(name = "record_id")
private Record record;
@ManyToOne
@JoinColumn(name = "document_model_id")
private DocumentModel documentModel;
@Entity
@Table(name = "document_model")
public class DocumentModel extends BaseEntity
//...
还有我的RecordService
,如下所示:
@Transactional
public class RecordService
private RecordRepository repository;
public RecordDTO update(RecordDTO dto)
Record record = repository.findById(dto.getId());
updateEntity(entity, dto);
repository.save(entity);
我还有一个通用事件监听器:
public class RecordEventListener implements PostUpdateEventListener
@Override
public void onPostUpdate(PostUpdateEvent event)
Object[] oldState = event.getOldState();
Object[] currentState = event.getState();
Object entity = event.getEntity();
//original Record id?
//...
我的理解是,当我调用更新方法(在服务层上)时,任何脏的 JPA 对象都将被更新/持久保存在数据库中,并且在关闭事务之前将生成 PostUpdate 事件以由侦听器处理。有时,Record 对象本身没有直接更改,因此不会为 Record 实体本身生成 PostUpdateEvent,而只会为 Record 对象图上的其他受影响的 JPA 实体生成 PostUpdateEvent,这是预期的。
是否有可能通过事务信息通过repository.save(entity);
方法调用以某种方式获取触发保存的原始对象?我需要以某种方式访问它的 ID。
【问题讨论】:
【参考方案1】:“原始身份”是什么意思? id 不能更改,因此对于“当前实体”而言,它与将实体传递给 save
时相同。 PostUpdateEvent
甚至有一个 getId
方法可以用于此目的。
【讨论】:
我的意思是传递给repository.save(entity);
方法的实体的原始ID。换句话说,我需要知道记录 id。
我不明白你的意思。 “记录ID”是我假设的主键?这是您可以通过PostUpdateEvent#getId()
访问的内容
让我再试一次。 Record JPA 实体图与 Document 和 DocumentModel 对象相关。假设当我调用服务方法updateEntity(entity, dto)
时,我实际上更新了在 Record 对象图中找到的 DocumentModel 对象。然后,当我使用 Record 服务方法 repository.save(entity)
保存时,在事务关闭之前,DocumentModel 更新只有一个 PostUpdateEvent,即使我调用了 repository.save(entity)
并传入了一个记录参数。有没有办法检索repository.save(entity)
方法中传递的id?
哦,所以你想要“父”实体的 id。我不认为这是可能的。您可以将一个字段放入您的实体中,尽管它会捕获此引用并随后访问它。
正是如此。嗯,不确定是否将每个其他 JPA 实体上的 recordId 作为属性或确保每个对象都有一个链接到其父对象的属性(然后遍历任何 jpa 对象图,直到我到达顶部 = Record 对象)。我还考虑过在保存记录并从侦听器检索它之前缓存 transactionId -> recordId,但找不到如何从 @Transational 方法检索 transactionId。以上是关于如何访问从 Hibernate AbstractEvents 和 EventListeners 调用 repository.save(entity) 时使用的原始实体?的主要内容,如果未能解决你的问题,请参考以下文章
Spring @PreAuthorize 抛出 LazyInitializationException 从 Hibernate 访问惰性数据