2015-07-28 61 views
1

我正在为Hibernate(集成商的背景:https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch14.html#objectstate-decl-security)开发一个Integrator,即使用侦听器应该将我的数据从数据库中存储并将其转换为一个不同的形式在运行时处理。当使用.persist()保存数据时,此功能非常有效,但涉及交易的行为很奇怪。下面的代码是由Hibernate自己quickstart tutorial code当使用JPA事务进行查询时,Hibernate集成器导致刷新

// now lets pull events from the database and list them 
entityManager = entityManagerFactory.createEntityManager(); 
entityManager.getTransaction().begin(); 
List<Event> result = entityManager.createQuery("from Event", Event.class).getResultList(); 
for (Event event : result) { 
    System.out.println("Event (" + event.getDate() + ") : " + event.getTitle()); 
} 
entityManager.getTransaction().commit(); 
entityManager.close(); 

通知的异常交易开始/提交包裹查询选择数据。运行此给出查询后下面的输出完成:

01:01:59.111 [main] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(175) - committing 
01:01:59.112 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(149) - Processing flush-time cascades 
01:01:59.112 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener.prepareCollectionFlushes(189) - Dirty checking collections 
01:01:59.114 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener.logFlushResults(123) - Flushed: 0 insertions, 2 updates, 0 deletions to 2 objects 
01:01:59.114 [main] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener.logFlushResults(130) - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections 
01:01:59.114 [main] DEBUG org.hibernate.internal.util.EntityPrinter.toString(114) - Listing entities: 
01:01:59.114 [main] DEBUG org.hibernate.internal.util.EntityPrinter.toString(121) - org.hibernate.tutorial.em.Event{date=2015-07-28 01:01:57.776, id=1, title=Our very first event!} 
01:01:59.114 [main] DEBUG org.hibernate.internal.util.EntityPrinter.toString(121) - org.hibernate.tutorial.em.Event{date=2015-07-28 01:01:58.746, id=2, title=A follow up event} 
01:01:59.115 [main] DEBUG org.hibernate.SQL.logStatement(109) - update EVENTS set EVENT_DATE=?, title=? where id=? 
Hibernate: update EVENTS set EVENT_DATE=?, title=? where id=? 
01:01:59.119 [main] DEBUG org.hibernate.SQL.logStatement(109) - update EVENTS set EVENT_DATE=?, title=? where id=? 
Hibernate: update EVENTS set EVENT_DATE=?, title=? where id=? 
01:01:59.120 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(113) - committed JDBC Connection 
01:01:59.120 [main] DEBUG org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.close(201) - HHH000420: Closing un-released batch 
01:01:59.121 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.releaseConnection(246) - Releasing JDBC connection 
01:01:59.121 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.releaseConnection(264) - Released JDBC connection 
01:01:59.121 [main] DEBUG org.hibernate.internal.SessionFactoryImpl.close(1339) - HHH000031: Closing 

看来,由于Integrator做了修改的实体问题,它被标记为“脏”,并在提交这个奇怪的交易,它绕过我的事件听众,并以错误的格式写回数值!我在代码中进行了一些挖掘,结果发现org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(FlushEvent, PersistenceContext)被上面的调用并试图获得EventType.FLUSH_ENTITY的侦听器。不幸的是,为这个EventType添加的听众永远不会在我的Integrator中被调用。我如何在这种情况下编写我的Integrator以正确行为,以便我可以“撤销”在运行时发生的与我的实体发生的转换,而不会将错误的值刷新?

回答

0

最终问题是由于事件监听器的EventType s增加了EventListenerRegistry。使用EventType.POST_LOAD的所有读操作与EventType.PRE_UPDATEEventType.PRE_INSERT结合起来用于写入,这些写入调用辅助方法以同样的方式进行处理。

为了防止在实体更新后不必要的写入,在EntityEntry被称为loadedState的情况下重置用于跟踪的数据是个好主意。这是Hibernate 4中的一个私有字段,因此您需要使用Reflection,但是在Hibernate 5中,它可以通过getLoadedState()方法获得。还有一个问题是,需要更新PreInsertEventPreUpdateEvent实际将值清空到数据库时所使用的“状态”值,这些值可以从各自定义的getState()方法中检索。

相关问题