3

I'm using the following code to initialize my Hibernate Search index:

EntityManager em = ...
FullTextEntityManager fullTextEM = Search.getFullTextEntityManager(em);
fullTextEM.createIndexer().startAndWait();

Now when I execute this code, I'm getting the following exception:

ERROR: HSEARCH000058: HSEARCH000116: Unexpected error during MassIndexer operation
org.hibernate.TransientObjectException: cannot lock an unsaved transient instance: com.example.hs.model.Division
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:75)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:724)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:717)
at org.hibernate.internal.SessionImpl.access$1700(SessionImpl.java:170)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2276)
at org.hibernate.search.batchindexing.impl.EntityConsumerLuceneWorkProducer.indexAllQueue(EntityConsumerLuceneWorkProducer.java:130)
at org.hibernate.search.batchindexing.impl.EntityConsumerLuceneWorkProducer.run(EntityConsumerLuceneWorkProducer.java:102)
at org.hibernate.search.batchindexing.impl.OptionallyWrapInJTATransaction.run(OptionallyWrapInJTATransaction.java:112)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)

In this case, the com.example.hs.model.Division class does have two @Transient annotations for methods that calculate a return value from a HashMap. The HashMap is retrieved via Hibernate as follows:

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "division_id", referencedColumnName = "id")
@MapKey(name = "language")
@Field(name="name")
@FieldBridge(impl = com.example.hs.search.LanguageDivisionTextBridge.class)
protected Map<Language, DivisionText> getDivisionTextMap() {
    return divisionTextMap;
}

As you can see, I am using a custom FieldBridge to help in the mapping. The DivisionText class is also marked with the @Indexed annotation and is successfully being indexed.

The full set of source can be found at:

https://github.com/jsvazic/hibernate-search-example

Any help would be greatly appreciated.

John S
  • 1,695
  • 2
  • 14
  • 25

1 Answers1

3

Your problem is not related to the @Transient annotation inside Foo, but to Foo as a whole. Some code inside the indexing procedure is trying to call Session.lock(foo), but at a time when foo is still just a plain object, before having been assigned to the session using Session.save or Session.persist. Maybe it would help to add a cascade=PERSIST parameter to the annotation on the foo field in your parent object, as explained here.

Community
  • 1
  • 1
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • I spoke too soon. Seems that the problem still exists. I have the ear of one of the Hibernate Search team, so I'm hoping that they can help. Sample code can be found at [https://github.com/jsvazic/hibernate-search-example](https://github.com/jsvazic/hibernate-search-example) – John S Apr 10 '12 at 02:12
  • Just a quick update, but I've adjusted the sample code to be much, much simpler. It seems the problem is specifically in the Division class, since DivisionText is working just fine, i.e. when I add the @Indexed annotation on Division, it fails. – John S Apr 11 '12 at 21:34
  • And where in your example is the `com.example.Foo`? Now that you have that code sample, please update your question to reflect it. – Marko Topolnik Apr 11 '12 at 21:47
  • Good point, sorry for that. The question has been updated to reflect the sample code and the simpler case. – John S Apr 12 '12 at 02:39
  • So let's review what you've done... how come you don't have `cascade=PERSIST` (or `ALL`) on `DivisionText.division`? – Marko Topolnik Apr 12 '12 at 11:43
  • An oversight on my part, but I've tried adding it with no success. I'll update GitHub accordingly. – John S Apr 12 '12 at 14:58
  • I realized that indexing doesn't actually write anything to db, it just reads. So if it tries to lock a transient instance, that instance came out of Hibernate in persistent state and then was evicted, probably at session.close(), and after that some code is trying to lock it. – Marko Topolnik Apr 12 '12 at 16:07
  • I've looked into the code of [EntityConsumerLuceneworkProducer](http://grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate-search/4.0.0.Alpha2/org/hibernate/search/batchindexing/impl/EntityConsumerLuceneworkProducer.java#EntityConsumerLuceneworkProducer.indexAllQueue%28org.hibernate.Session%29), it's messy as hell. – Marko Topolnik Apr 12 '12 at 16:18
  • They have just released a new rev of Hibernate search (4.1). I was using 4.0, so I'm not sure which version of the code you were looking at. I suspect that it is still messy, but still. – John S Apr 12 '12 at 17:29
  • If you click on the link under the class name in my previous comment, you can see for yourself. – Marko Topolnik Apr 12 '12 at 17:31
  • Thanks for your help Marko. I'll mark this one accepted as I'm getting nowhere with this one. Nobody on the Hibernate forums is assisting either. I appreciate the help, but we've decided to move on use LIKE statements instead. – John S Apr 23 '12 at 01:50
  • If you ever need to return to Lucene, my warm suggestion is to skip everything else in between and use Lucene directly, writing all the necessary code yourself. Lucene is a fantastic library, not matched in quality by anything else around it in the Lucene ecosystem. You'll be doing yourself a great favor if you invest in learning the Lucene API. – Marko Topolnik Apr 23 '12 at 05:31