我正在尝试使用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
我花了一天的时间进行调试,但我仍然不知道为什么。你能帮我解释一下吗?
答案 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方法的相同缺陷,因此删除 操作无法审核。