如何访问从 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) 时使用的原始实体?的主要内容,如果未能解决你的问题,请参考以下文章

如何访问 Hibernate 统计信息

Spring @PreAuthorize 抛出 LazyInitializationException 从 Hibernate 访问惰性数据

是否应该从数据访问层或接口返回原始的 Hibernate 注释 POJO?

Hibernate缓存如何实现

如何使用 Hibernate 处理多个数据库模式?

Hibernate - 从多对多关系访问字段