Java Spring JPA有时会跳过插入实体

Java Spring JPA有时会跳过插入实体,java,hibernate,jpa,spring-boot,Java,Hibernate,Jpa,Spring Boot,我有一个springboot应用程序,并有一个自定义实现来记录JPA实体的更改历史 我的主要实体是Test,它从基类扩展而来。基类具有以下注释 @EntityListeners(HistoryEntityUpdater.class) @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = "object_type") 我有一个自定义实体侦听器,其方法用@PostPersist和@PostUpdate

我有一个springboot应用程序,并有一个自定义实现来记录JPA实体的更改历史

我的主要实体是Test,它从基类扩展而来。基类具有以下注释

@EntityListeners(HistoryEntityUpdater.class)
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "object_type")
我有一个自定义实体侦听器,其方法用
@PostPersist
@PostUpdate
注释。在这些方法中,我创建了
TestHistory
的一个实例,并调用
entityManager.persist
。虽然这是可行的,但是一些历史记录并没有被插入。这是调用save但数据库未更新时的日志

2016-04-22 19:57:58.428 TRACE 18060 --- [nio-9285-exec-2] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Releasing statement [sql : 'update managed_object set last_updated_time=?, name=?, workflow_status=? where id=?', parameters : ['2016-04-22 19:57:26.185','tests1','ERROR',1]]
2016-04-22 19:57:58.429 TRACE 18060 --- [nio-9285-exec-2] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Closing prepared statement [sql : 'update managed_object set last_updated_time=?, name=?, workflow_status=? where id=?', parameters : ['2016-04-22 19:57:26.185','tests1','ERROR',1]]
2016-04-22 19:57:58.429 TRACE 18060 --- [nio-9285-exec-2] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Starting after statement execution processing [ON_CLOSE]
2016-04-22 19:57:58.429 TRACE 18060 --- [nio-9285-exec-2] o.h.internal.util.SerializationHelper    : Starting clone through serialization
2016-04-22 19:57:58.429 TRACE 18060 --- [nio-9285-exec-2] o.h.internal.util.SerializationHelper    : Starting serialization of object [2016-04-22T14:27:26.185Z]
2016-04-22 19:57:58.429 TRACE 18060 --- [nio-9285-exec-2] o.h.internal.util.SerializationHelper    : Starting deserialization of object
2016-04-22 19:57:58.433 TRACE 18060 --- [nio-9285-exec-2] o.h.internal.util.SerializationHelper    : Attempting to locate class [java.time.Ser]
2016-04-22 19:57:58.434 DEBUG 18060 --- [nio-9285-exec-2] c.b.b.m.db.history.HistoryEntityUpdater  : postUpdate com.xyz.model.db.Test@4dcfc8b8
2016-04-22 19:57:58.435 TRACE 18060 --- [nio-9285-exec-2] o.hibernate.engine.spi.IdentifierValue   : ID unsaved-value strategy UNDEFINED
2016-04-22 19:57:58.436 TRACE 18060 --- [nio-9285-exec-2] o.h.e.i.AbstractSaveEventListener        : Transient instance of: com.xyz.model.db.history.TestHistory
2016-04-22 19:57:58.436 TRACE 18060 --- [nio-9285-exec-2] o.h.e.i.DefaultPersistEventListener      : Saving transient instance
2016-04-22 19:57:58.437 DEBUG 18060 --- [nio-9285-exec-2] o.h.e.i.AbstractSaveEventListener        : Generated identifier: component[id,revisionTime,revisionType]{revisionType=UPDATED, id=1, revisionTime=Fri Apr 22 19:57:58 IST 2016}, using strategy: org.hibernate.id.CompositeNestedGeneratedValueGenerator
2016-04-22 19:57:58.437 TRACE 18060 --- [nio-9285-exec-2] o.h.e.i.AbstractSaveEventListener        : Saving [com.xyz.model.db.history.TestHistory#component[id,revisionTime,revisionType]{revisionType=UPDATED, id=1, revisionTime=Fri Apr 22 19:57:58 IST 2016}]
2016-04-22 19:57:58.437 TRACE 18060 --- [nio-9285-exec-2] org.hibernate.engine.spi.ActionQueue     : Adding an EntityInsertAction for [com.xyz.model.db.history.TestHistory] object
2016-04-22 19:57:58.437 TRACE 18060 --- [nio-9285-exec-2] org.hibernate.engine.spi.ActionQueue     : Adding insert with no non-nullable, transient entities: [EntityInsertAction[com.xyz.model.db.history.TestHistory#com.xyz.model.db.history.HistoryObject$HistoryId@4b74eea0]]
2016-04-22 19:57:58.437 TRACE 18060 --- [nio-9285-exec-2] org.hibernate.engine.spi.ActionQueue     : Adding resolved non-early insert action.
2016-04-22 19:57:58.437 TRACE 18060 --- [nio-9285-exec-2] o.h.a.i.UnresolvedEntityInsertActions    : No unresolved entity inserts that depended on [[com.xyz.db.history.TestHistory#com.xyz.db.history.HistoryObject$HistoryId@4b74eea0]]
2016-04-22 19:57:58.437 TRACE 18060 --- [nio-9285-exec-2] o.h.a.i.UnresolvedEntityInsertActions    : No entity insert actions have non-nullable, transient entity dependencies.
2016-04-22 19:57:58.438 TRACE 18060 --- [nio-9285-exec-2] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Starting after statement execution processing [ON_CLOSE]
2016-04-22 19:57:58.438 TRACE 18060 --- [nio-9285-exec-2] o.h.e.i.AbstractFlushingEventListener    : Post flush
2016-04-22 19:57:58.438 TRACE 18060 --- [nio-9285-exec-2] org.hibernate.internal.SessionImpl       : before transaction completion
2016-04-22 19:57:58.440 DEBUG 18060 --- [nio-9285-exec-2] o.h.e.t.internal.jdbc.JdbcTransaction    : committed JDBC Connection
2016-04-22 19:57:58.440 DEBUG 18060 --- [nio-9285-exec-2] o.h.e.t.internal.jdbc.JdbcTransaction    : re-enabling autocommit
2016-04-22 19:57:58.441 TRACE 18060 --- [nio-9285-exec-2] o.h.e.t.i.TransactionCoordinatorImpl     : after transaction completion
2016-04-22 19:57:58.442 TRACE 18060 --- [nio-9285-exec-2] org.hibernate.internal.SessionImpl       : after transaction completion
2016-04-22 19:57:58.443 TRACE 18060 --- [nio-9285-exec-2] org.hibernate.internal.SessionImpl       : Closing session
2016-04-22 19:57:58.443 TRACE 18060 --- [nio-9285-exec-2] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Closing JDBC container [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@5be5a598]
2016-04-22 19:57:58.443 DEBUG 18060 --- [nio-9285-exec-2] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : HHH000420: Closing un-released batch
2016-04-22 19:57:58.443 TRACE 18060 --- [nio-9285-exec-2] o.h.e.j.internal.LogicalConnectionImpl   : Closing logical connection
2016-04-22 19:57:58.443 DEBUG 18060 --- [nio-9285-exec-2] o.h.e.j.internal.LogicalConnectionImpl   : Releasing JDBC connection
2016-04-22 19:57:58.443 DEBUG 18060 --- [nio-9285-exec-2] o.h.e.j.internal.LogicalConnectionImpl   : Released JDBC connection
2016-04-22 19:57:58.443 TRACE 18060 --- [nio-9285-exec-2] o.h.e.j.internal.LogicalConnectionImpl   : Logical connection closed

HistoryEntityUpdater
上的
postUpdate
postPersist
方法用
@Transactional
注释,JPA规范声明EntityListeners不应使用EntityManager。 这使得它们在大多数用例中都是无用的,包括您的用例

我也不知道

从stacktrace看,JDBC事务已经提交,entitymanager已刷新。 因此,至少在侦听器运行时没有任何事务。这可能会导致写入的历史实体未写入数据库的情况。 EntityListener由hibernate而不是spring调用,因此侦听器上的任何@Transactional注释都无法工作

最后还有一个解决方案,使用“Envers”实现实体审核:


JPA规范规定EntityListeners不应使用EntityManager。 这使得它们在大多数用例中都是无用的,包括您的用例

我也不知道

从stacktrace看,JDBC事务已经提交,entitymanager已刷新。 因此,至少在侦听器运行时没有任何事务。这可能会导致写入的历史实体未写入数据库的情况。 EntityListener由hibernate而不是spring调用,因此侦听器上的任何@Transactional注释都无法工作

最后还有一个解决方案,使用“Envers”实现实体审核: