gpt4 book ai didi

java - JPA EntityManager 无法在 PostInsertEventListener 中刷新

转载 作者:行者123 更新时间:2023-12-02 10:35:52 24 4
gpt4 key购买 nike

我正在尝试使用 Hibernate 事件监听器编写审核日志,例如:PostInsertEventListener、PostUpdateEventListener 和 PostDeleteEventListener。但我在使用entityManager 将数据从持久上下文刷新到这些监听器中的数据库时遇到了问题:

这是源代码:

EntityA.class

@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;
}

BusinessService.java

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

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

EntityEventListenerRegistry.java:

@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中发生异常:

org.hibernate.AssertionFailure: null id in EntityA entry (don't flush the Session after an exception occurs)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:60)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:175)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:135)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1300)

调试了一天,还是不知道原因。能帮我解释一下吗?

最佳答案

我发现有些人已经告诉过您 Hibernate 的局限性。文档(Hibernate User Guide)说:

A callback method must not invoke EntityManager or Query methods!

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

您还可以在那里阅读有关审核的信息:https://www.baeldung.com/database-auditing-jpa

  • The pure JPA approach is the most basic and consists of using lifecycle callbacks. However, you are only allowed to modify the non-relationship state of an entity. This makes the @PreRemove callback useless for our purposes, as any settings you’ve made in the method will be deleted then along with the entity.
  • Envers is a mature auditing module provided by Hibernate. It is highly configurable and lacks the flaws of the pure JPA implementation. Thus, it allows us to audit the delete operation, as it logs into tables other than the entity’s table.

  • The Spring Data JPA approach abstracts working with JPA callbacks and provides handy annotations for auditing properties. It’s also ready for integration with Spring Security. The disadvantage is that it inherits the same flaws of the JPA approach, so the delete operation cannot be audited.

关于java - JPA EntityManager 无法在 PostInsertEventListener 中刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53295606/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com