我有一个带有JPA(Hibernate 5.0.11.Final)和Hibernate Search(5.5.5.Final)的WebAppilcation runnig,其中用户试图保存一个新实体。因此会有几个电话,如:
protected Object saveNewEntity(Object toSave) {
if (factory == null) {
factory = Persistence
.createEntityManagerFactory(DBBase.PERSISTENCE_UNIT);
}
EntityManager em = initEntityManager();
try {
em.setFlushMode(FlushModeType.COMMIT);
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(toSave);
transaction.commit();
} catch (Exception e) {
throw e;
} finally {
finalizeEntityManager(em);
}
return toSave;
}
protected void finalizeEntityManager(EntityManager em) {
if (em != null && em.isOpen()) {
em.close();
}
}
索引的实体也以这种方式保存。它没有级联,并且完全平坦(不涉及其他表)。
大多数情况下,这将运行良好,索引将更新。
但有时,我不知道为什么,会发生以下异常,因此索引不会更新:
2017-04-04 10:30:48,552 ERROR [LuceneBackendQueueTask:run:54] HSEARCH000073: Error in backend
java.nio.channels.OverlappingFileLockException
at sun.nio.ch.SharedFileLockTable.checkList(FileLockTable.java:255) ~[?:1.8.0_121]
at sun.nio.ch.SharedFileLockTable.add(FileLockTable.java:152) ~[?:1.8.0_121]
at sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1108) ~[?:1.8.0_121]
at java.nio.channels.FileChannel.tryLock(FileChannel.java:1155) ~[?:1.8.0_121]
at org.apache.lucene.store.NativeFSLockFactory.obtainFSLock(NativeFSLockFactory.java:114) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.apache.lucene.store.FSLockFactory.obtainLock(FSLockFactory.java:41) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.apache.lucene.store.BaseDirectory.obtainLock(BaseDirectory.java:45) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:775) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.createNewIndexWriter(IndexWriterHolder.java:123) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.getIndexWriter(IndexWriterHolder.java:89) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriter(AbstractWorkspaceImpl.java:112) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriterDelegate(AbstractWorkspaceImpl.java:198) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.applyUpdates(LuceneBackendQueueTask.java:80) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.run(LuceneBackendQueueTask.java:46) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.applyChangesets(SyncWorkProcessor.java:162) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.run(SyncWorkProcessor.java:148) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_121]
2017-04-04 10:30:48,555 ERROR [LogErrorHandler:handleException:67] HSEARCH000058: Exception occurred java.nio.channels.OverlappingFileLockException
Primary Failure:
Entity com.rhenus.de.cm.essentials.entities.ContractSearchEntity Id 96926 Work Type org.hibernate.search.backend.AddLuceneWork
java.nio.channels.OverlappingFileLockException
at sun.nio.ch.SharedFileLockTable.checkList(FileLockTable.java:255) ~[?:1.8.0_121]
at sun.nio.ch.SharedFileLockTable.add(FileLockTable.java:152) ~[?:1.8.0_121]
at sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1108) ~[?:1.8.0_121]
at java.nio.channels.FileChannel.tryLock(FileChannel.java:1155) ~[?:1.8.0_121]
at org.apache.lucene.store.NativeFSLockFactory.obtainFSLock(NativeFSLockFactory.java:114) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.apache.lucene.store.FSLockFactory.obtainLock(FSLockFactory.java:41) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.apache.lucene.store.BaseDirectory.obtainLock(BaseDirectory.java:45) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:775) ~[lucene-core-5.3.1.jar:5.3.1 1703449 - noble - 2015-09-17 01:38:09]
at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.createNewIndexWriter(IndexWriterHolder.java:123) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.getIndexWriter(IndexWriterHolder.java:89) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriter(AbstractWorkspaceImpl.java:112) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriterDelegate(AbstractWorkspaceImpl.java:198) ~[hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.applyUpdates(LuceneBackendQueueTask.java:80) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.run(LuceneBackendQueueTask.java:46) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.applyChangesets(SyncWorkProcessor.java:162) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.run(SyncWorkProcessor.java:148) [hibernate-search-engine-5.5.5.Final.jar:5.5.5.Final]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_121]
我不手动锁定或更新索引,也不是不同的线程,应用程序或其他任何东西使用的索引。 我已经读过,如果实体已经有了id,并且在stacktrace中声明了id,那么就会发生这种情况。但我绝对不会持有一个带有id的实体。那么可能存在并发效应?
任何提示和帮助表示赞赏。如果您需要更多信息,请询问,我会提供。谢谢。
答案 0 :(得分:3)
问题实际上不是在Hibernate Search中,而是在前三行代码中。
你说过“不同的线程,应用程序或其他任何东西都使用索引”,但你也建议这是一个Web应用程序,因此它很可能需要对你无法控制的事件作出反应,即使你没有不要期待。
什么是保证不会同时调用这些初始代码行? EntityManagerFactory
的初始化可能会被多次触发,但没有代码关闭已经启动的副本。
实际上,您正在运行Hibernate Search的多个副本并且正在努力获取独占索引锁。
让我建议永远不要禁用锁定机制:它旨在保护您免受类似的错误。默认情况下启用它是有充分理由的。
我还建议使用一些标准方法初始化Hibernate和/或JPA,任何流行的JavaEE容器(如WildFly)或框架都可能“做得对”,还有一些最先进的容器可以自动启用一些疯狂的优化。