I'm using the following piece of code to reindex my database into hibernate search. On my dev database it works fine, but on the production system I get errors that a lazy collection (Record.entries) can not be initialized; that there is no Session. This also happens for references to other objects. It appears that after the call to clear(), the objects themselves are loaded but lazy references cannot be resolved even though the transaction is still ongoing.
Strangely, the stack trace passes through fullText.index(), in which case the transaction IS still live, so there should still be a session. Clearly there is something funny going on.
I tried to add a fullText.refresh() in the hopes it would prevent this, but it didn't.
Could there be some lazy instances being cached but not reattached to the session somehow?
Any ideas on how to find a solution for this would be great - thanks in advance!
I'm using Hibernate Search 3.0.1.GA
Code:
FullTextEntityManager fullText = getFullText();
fullText.setFlushMode(FlushModeType.COMMIT);
final int batchSize=5000; // matches value in persistence.xml
int i=0;
for(Class<?> clazz : new Class[] {Record.class, Contact.class}) {
// First dump everything we already know about that class
fullText.purgeAll(clazz);
javax.persistence.Query queryCount = em.createQuery("select count(x.id) from "+clazz.getName()+" x where x.removed = false");
int count = ((Long)queryCount.getSingleResult()).intValue();
for(int offset=0; offset < count; ) {
javax.persistence.Query query = em.createQuery("select object(x) from "+clazz.getName()+" x where x.removed = false");
query.setFirstResult(offset);
int batchRemaining = batchSize - (i%batchSize);
query.setMaxResults(batchRemaining);
List<?> results = query.getResultList();
for(Object ent : results) {
fullText.refresh(ent);
fullText.index(ent); // Might throw an exception here
}
logger.info("Indexed "+(offset+results.size())+" of "+count+" instances of "+clazz.getName());
i += results.size();
offset += results.size();
// Did we complete a full batch? If so, we can dump all the old objects
if(results.size() == batchRemaining) {
fullText.clear();
} else if(results.size() == 0) {
// Don't loop forever ...
break;
}
}
}
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: books.db.Record.entries, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentColl
ection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(Abstract
PersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)
at org.hibernate.search.engine.DocumentBuilder.buildDocumentFields(DocumentBuilder.java:564)
at org.hibernate.search.engine.DocumentBuilder.getDocument(DocumentBuilder.java:524)
at org.hibernate.search.engine.DocumentBuilder.addWorkToQueue(DocumentBuilder.java:441)
at org.hibernate.search.backend.impl.BatchedQueueingProcessor.processWorkByLayer(BatchedQueueingProcessor.java:1
38)
at org.hibernate.search.backend.impl.BatchedQueueingProcessor.prepareWorks(BatchedQueueingProcessor.java:122)
at org.hibernate.search.backend.impl.BatchedQueueingProcessor.add(BatchedQueueingProcessor.java:105)
at org.hibernate.search.backend.impl.PostTransactionWorkQueueSynchronization.add(PostTransactionWorkQueueSynchro
nization.java:36)
at books.db.search.SafeWorkerImpl.performWork(SafeWorkerImpl.java:33)
at org.hibernate.search.impl.FullTextSessionImpl.index(FullTextSessionImpl.java:140)
at org.hibernate.search.jpa.impl.FullTextEntityManagerImpl.index(FullTextEntityManagerImpl.java:65)
at books.service.impl.SearchServiceImpl.reindex(SearchServiceImpl.java:275)
... more ....