JPA EntityManager无法在PostInsertEventListener中刷新

时间:2018-11-14 08:12:32

标签: java hibernate spring-boot jpa

我正在尝试使用Hibernate事件侦听器(例如PostInsertEventListener,PostUpdateEventListener和PostDeleteEventListener)编写审核日志。但是我有一个问题,例如使用entityManager在这些侦听器中将数据从持久性上下文刷新到数据库:

这是源代码:

EntityA.class

dataGridView1_CellValidating

BusinessService.java

@Entity
@Table(name = "ENTITY_A")
public class EntityA implements Serializable {
  private static final long serialVersionUID = -8674903027075338289L;

  @Id
  @Column(name = "ENTITY_A_ID")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @SortableField
  private Long buStepId;


  @Column(name = "ENTITY_A_CODE", unique = true)
  private String buStepCode;


  @Column(name = "ENTITY_A_NAME")
  private String buStepName;

  @OneToMany(mappedBy = "buStep", fetch = FetchType.LAZY)
  private List<BuEvent> BuEvents;

  @OneToMany(mappedBy = "buStep", fetch = FetchType.LAZY)
  private Set<BuEventFlow> BuEventFlows;

  @ManyToOne
  @JoinColumn(name = "GS_STATUS_ID", referencedColumnName = "STATUS_ID")
  private RefStatus refGsStatus;

  @ManyToOne
  @JoinColumn(name = "GT_STATUS_ID", referencedColumnName = "STATUS_ID")
  private RefStatus refGtStatus;

  @ManyToOne
  @JoinColumn(name = "GS_VERSION_ID", referencedColumnName = "VERSION_ID")
  private RefVersion refGsVersion;

  @ManyToOne
  @JoinColumn(name = "GT_VERSION_ID", referencedColumnName = "VERSION_ID")
  @AuditableField(name = "GT Version")
  private RefVersion refGtVersion;

  @ManyToOne
  @JoinColumn(name = "EVO_TYPE_ID")
  private RefEvoType refEvoType;

  @Column(name = "TURN")
  private Long turn;

  @ManyToOne
  @JoinColumn(name = "step_family_id", nullable = true)
  private RefStepFamily buStepFamily;

  @OneToMany(mappedBy = "buStep", fetch = FetchType.LAZY)
  private List<BuStepFlow> buStepFlows;

  @Transient
  private Long stepFamilyId;
}

EntityEventListenerRegistry.java:

@Service
public class BusinessService {
  @PersistenceContext
  protected EntityManager entityManager;

  public void createEntityA() {
    EntityA entityA = createPojoEntityA();
    entityManager.persist(entityA);
  }
}

然后方法@Component public class EntityEventListenerRegistry implements PostInsertEventListener, PostUpdateEventListener, PostDeleteEventListener { @PersistenceContext EntityManager entityManager; @PostConstruct protected void init() { HibernateEntityManagerFactory hibernateEntityManagerFactory = (HibernateEntityManagerFactory) this.emf; SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory(); EventListenerRegistry registry = sessionFactoryImpl.getServiceRegistry().getService(EventListenerRegistry.class); registry.appendListeners(EventType.POST_INSERT, this); registry.appendListeners(EventType.POST_UPDATE, this); registry.appendListeners(EventType.POST_DELETE, this); } @Override public void onPostInsert(PostInsertEvent event) { // Do something with entityA before entityManager.flush(); // Do something with entityA after } ... } 中发生异常:

onPostInsert

我花了一天的时间进行调试,但我仍然不知道为什么。你能帮我解释一下吗?

1 个答案:

答案 0 :(得分:1)

我看到有些人已经告诉过您有关Hibernate的限制。 文档(Hibernate User Guide)说:

  

回调方法不得调用EntityManager或Query方法!

无论如何,要解决审核任务,您可以使用Hibernate Envers:http://hibernate.org/orm/envers/

您还可以在此处了解有关审核的信息:https://www.baeldung.com/database-auditing-jpa

  
      
  • 纯JPA方法是最基本的方法,包括使用生命周期回调。但是,只允许您修改   实体的非关系状态。这使得@PreRemove   回调对我们无用,因为您在   方法将被删除,然后与实体一起删除。
  •   
  • Envers是Hibernate提供的成熟的审核模块。它是高度可配置的,并且没有纯JPA的缺陷   实施。因此,它允许我们审核删除操作,如下   它会登录到实体表以外的表。

  •   
  • Spring Data JPA方法抽象了使用JPA回调的工作,并为审核属性提供了方便的注释。这也是   准备与Spring Security集成。缺点是   它继承了JPA方法的相同缺陷,因此删除   操作无法审核。

  •