hibernate - 未加载实体集合时索引失败并使用 LazyInitializationException 中断事务
问题描述
我在我的 UI 中加载了一个实体,更改了一些内容并使用新事务更新了我的实体,但是 Hibernate Search 在我的事务中拦截并尝试更新搜索索引。那会找到,除非它尝试加载一个@IndexedEmbedded()
未使用的带有注释的集合,因此会抛出一个LazyInitializationException
.
我怎样才能防止这种情况?
Caused by: org.hibernate.HibernateException: Error while indexing in Hibernate Search (before transaction completion)
at org.hibernate.search.event.impl.EventSourceTransactionContext$DelegateToSynchronizationOnBeforeTx.doBeforeTransactionCompletion(EventSourceTransactionContext.java:173)
at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:954)
at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:525)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2480)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:98)
... 76 common frames omitted
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.foo.Bar, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:597)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:216)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:147)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:188)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFieldsForEmbeddedObjects(DocumentBuilderIndexedEntity.java:553)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFields(DocumentBuilderIndexedEntity.java:482)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFieldsForEmbeddedObjects(DocumentBuilderIndexedEntity.java:593)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFields(DocumentBuilderIndexedEntity.java:482)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.getDocument(DocumentBuilderIndexedEntity.java:402)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.createAddWork(DocumentBuilderIndexedEntity.java:299)
at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.addWorkToQueue(DocumentBuilderIndexedEntity.java:241)
at org.hibernate.search.engine.impl.WorkPlan$PerEntityWork.enqueueLuceneWork(WorkPlan.java:560)
at org.hibernate.search.engine.impl.WorkPlan$PerClassWork.enqueueLuceneWork(WorkPlan.java:322)
at org.hibernate.search.engine.impl.WorkPlan.getPlannedLuceneWork(WorkPlan.java:188)
at org.hibernate.search.backend.impl.WorkQueue.prepareWorkPlan(WorkQueue.java:115)
at org.hibernate.search.backend.impl.BatchedQueueingProcessor.prepareWorks(BatchedQueueingProcessor.java:55)
at org.hibernate.search.backend.impl.PostTransactionWorkQueueSynchronization.beforeCompletion(PostTransactionWorkQueueSynchronization.java:67)
at org.hibernate.search.event.impl.EventSourceTransactionContext$DelegateToSynchronizationOnBeforeTx.doBeforeTransactionCompletion(EventSourceTransactionContext.java:170)
... 84 common frames omitted
解决方案
发生这种情况时,通常意味着您关闭了用于加载实体的会话,并尝试使用另一个会话更新实体。它发生在某些框架中,由于某种原因,您需要在加载和实际更新之间序列化实体。
最简单的解决方案是:不要在不同的会话中分离和使用实体,它只会让你头疼。而且我说的不仅仅是休眠搜索。
如果您真的想这样做,这是可能的,但并不像最初看起来那么明显。
至少有一些方法可以避免在 Wicket 中使用分离的实体。对于其他框架,在不了解您的 UI 框架的情况下,我真的无能为力。如果它是我不知道的 UI 框架,我怀疑我能提供帮助,但值得一试;)
如果您决定提供更多信息,请至少提及:您正在使用的 Hibernate ORM 和 Hibernate Search 版本,以及您在与 Session/EntityManager ( .persist()
, .merge()
, .saveOrUpdate()
, ...) 和 UI交互时使用的确切代码与在组件之间存储/传输实体相关的代码。
推荐阅读
- html - 寻找可以修复数据类型冲突问题的 html 输入属性或引导类
- node.js - VSCode 异步 setStatusBarMessage
- php - Laravel 5.5 AJAX 实时数据搜索不起作用
- mysql - 在多线程中使用相同的数据库连接时发生了什么?
- swift - 在 PDF 中绘制 NSString(水印)
- python - 如何成功安装mysqlclient
- vue.js - VueJs - Element UI:如何更改 el-date-picker
- ignite - apache点燃spring数据是否支持order by子句
- .htaccess - 如何将所有请求链接到 index.php 并将 sitemap.xml 链接到 .htaccess 中的 sitemap.php
- ruby-on-rails - 控制器子目录中的操作路径是什么?