[
http://opensource.atlassian.com/projects/hibernate/browse/HSEARCH-662?pag...
]
Guillaume Smet commented on HSEARCH-662:
----------------------------------------
Hello,
I confirm that this is a real bug and here is an explanation and a proposal on how to fix
it.
The problem is that in the WorkPlan, works are stored by id in the map:
{code}
private final HashMap<Serializable, PerEntityWork<T>> entityById = new
HashMap<Serializable, PerEntityWork<T>>().
{code}
This id is extracted using the extractProperId() method which is:
{code}
private Serializable extractProperId(Work<T> work) {
T entity = work.getEntity();
// 1) entity is null for purge operation, which requires to trust the work id
// 2) types mapped as provided id require to use the work id
// 3) when Hibernate identifier rollback is used && this identifier is our same
id source, we need to get the value from work id
if ( entity == null ||
documentBuilder.requiresProvidedId() ||
( work.isIdentifierWasRolledBack() && documentBuilder.isIdMatchingJpaId() )
) {
return work.getId();
}
else {
return documentBuilder.getId( entity );
}
}
{code}
In the case explained above, we are in the "return documentBuilder.getId( entity
);" case and the documentBuilder is a DocumentBuilderContainedEntity which returns
null as the id:
{code}
@Override
public Serializable getId(Object entity) {
//this is not an indexed entity
return null;
}
{code}
So for all the @ContainedIn entities, the id is null and when you add a new one in the
queue, it overwrites the previous one and thus you have only one entity reindexed.
I think the easiest way to fix the problem is to also return work.getId() in the case of
@ContainedIn entities. IMHO, I would test if documentBuilder.getId( entity ) returns null
and, if so, I would return the work.getId(). It's the most solid solution on the long
term, rather than special casing the @ContainedIn case.
Something along these lines should fix it:
{code}
private Serializable extractProperId(Work<T> work) {
T entity = work.getEntity();
// 1) entity is null for purge operation, which requires to trust the work id
// 2) types mapped as provided id require to use the work id
// 3) when Hibernate identifier rollback is used && this identifier is our same
id source, we need to get the value from work id
if ( entity == null ||
documentBuilder.requiresProvidedId() ||
( work.isIdentifierWasRolledBack() && documentBuilder.isIdMatchingJpaId() )
) {
return work.getId();
}
else {
Serializable id = documentBuilder.getId( entity );
if ( id != null ) {
return id;
} else {
return work.getId();
}
}
}
{code}
Feel free to ask any further question if my explanation isn't clear. It would be nice
to have it fixed in the next version of Hibernate Search.
--
Guillaume
Re-indexing failure in @IndexedEmbedded entities in @ManyToOne
relationship
---------------------------------------------------------------------------
Key: HSEARCH-662
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HSEARCH-662
Project: Hibernate Search
Issue Type: Bug
Components: engine
Affects Versions: 3.3.0.Final
Environment: Hibernate 3.6.0
Reporter: Kyrill Alyoshin
Priority: Blocker
Attachments: hibernate_search_bug.zip
What is happening seems to be this:
Let's say we have an @Indexed entity called Son. It has @IndexedEmbedded parent
property called Dad in @ManyToOne relationship. Dad is @ContainedIn and has @Field on one
of its fields. I am demonstrating a condition when more than one Dads are updated in a
single session, only one would be re-indexed, the rest will fail to be re-indexed.
I am attaching a simple IDEA project that clearly demonstrates what is going on. I
believe that this is a very serious bug. (Note: I removed hibernate-3.6.0.jar from the lib
directory to minimize the size of the zip file under 10M, the rest of the jars are
there).
Please run BugDemonstrationTest#showBug test method to see everything.
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira