[hibernate-commits] Hibernate SVN: r15386 - in search/trunk/src: java/org/hibernate/search/impl and 2 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Fri Oct 24 10:22:27 EDT 2008
Author: hardy.ferentschik
Date: 2008-10-24 10:22:27 -0400 (Fri, 24 Oct 2008)
New Revision: 15386
Modified:
search/trunk/src/java/org/hibernate/search/FullTextSession.java
search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
search/trunk/src/test/org/hibernate/search/test/SearchTestCase.java
search/trunk/src/test/org/hibernate/search/test/inheritance/InheritanceTest.java
Log:
HSEARCH-262
purging an entity also purges also subclasses from the index
Modified: search/trunk/src/java/org/hibernate/search/FullTextSession.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/FullTextSession.java 2008-10-24 14:00:30 UTC (rev 15385)
+++ search/trunk/src/java/org/hibernate/search/FullTextSession.java 2008-10-24 14:22:27 UTC (rev 15386)
@@ -34,20 +34,22 @@
SearchFactory getSearchFactory();
/**
- * Remove a particular entity from a particular class of an index.
+ * Remove the entity with the type <code>entityType</code> and the identifier <code>id</code> from the index.
+ * If <code>id == null</code> all indexed entities of this type and its indexed subclasses are deleted. In this
+ * case this method behaves like {@link #purgeAll(Class<?>)}.
*
- * @param entityType
- * @param id
+ * @param entityType The type of the entity to delete.
+ * @param id The id of the entity to delete.
*
- * @throws IllegalArgumentException if entityType is null or not an @Indexed entity type
+ * @throws IllegalArgumentException if entityType is <code>null</codE> or not an @Indexed entity type.
*/
public void purge(Class<?> entityType, Serializable id);
/**
- * Remove all entities from a particular class of an index.
+ * Remove all entities from of particular class and all its subclasses from the index.
*
- * @param entityType
- * @throws IllegalArgumentException if entityType is null or not an @Indexed entity type
+ * @param entityType The class of the entities to remove.
+ * @throws IllegalArgumentException if entityType is <code>null</code> or not an @Indexed entity type.
*/
public void purgeAll(Class<?> entityType);
Modified: search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java 2008-10-24 14:00:30 UTC (rev 15385)
+++ search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java 2008-10-24 14:22:27 UTC (rev 15386)
@@ -7,6 +7,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
@@ -43,9 +44,9 @@
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.SearchFactory;
+import org.hibernate.search.backend.TransactionContext;
import org.hibernate.search.backend.Work;
import org.hibernate.search.backend.WorkType;
-import org.hibernate.search.backend.TransactionContext;
import org.hibernate.search.backend.impl.EventSourceTransactionContext;
import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.engine.SearchFactoryImplementor;
@@ -62,6 +63,7 @@
* @author Hardy Ferentschik
*/
public class FullTextSessionImpl implements FullTextSession, SessionImplementor {
+
private final Session session;
private final SessionImplementor sessionImplementor;
private transient SearchFactoryImplementor searchFactory;
@@ -69,9 +71,9 @@
public FullTextSessionImpl(org.hibernate.Session session) {
- this.session = (Session) session;
- this.transactionContext = new EventSourceTransactionContext( (EventSource) session );
- this.sessionImplementor = (SessionImplementor) session;
+ this.session = ( Session ) session;
+ this.transactionContext = new EventSourceTransactionContext( ( EventSource ) session );
+ this.sessionImplementor = ( SessionImplementor ) session;
}
/**
@@ -85,10 +87,7 @@
}
/**
- * Remove all entities from a particular class of an index.
- *
- * @param entityType
- * @throws IllegalArgumentException if entityType is null or not an @Indexed entity type
+ * {@inheritDoc}
*/
public void purgeAll(Class entityType) {
purge( entityType, null );
@@ -100,32 +99,39 @@
}
/**
- * Remove a particular entity from a particular class of an index.
- *
- * @param entityType
- * @param id
- * @throws IllegalArgumentException if entityType is null or not an @Indexed entity type
+ * {@inheritDoc}
*/
public void purge(Class<?> entityType, Serializable id) {
- if ( entityType == null ) return;
+ if ( entityType == null ) {
+ return;
+ }
+
+ // accessing the document builders is not strictly necessary but a small optimization plus let's make sure the
+ // client didn't mess something up.
SearchFactoryImplementor searchFactoryImplementor = getSearchFactoryImplementor();
- // not strictly necessary but a small optimization plus let's make sure the
- // client didn't mess something up.
+ DocumentBuilder builder = searchFactoryImplementor.getDocumentBuilder( entityType );
+ if ( builder == null ) {
+ String msg = "Entity to index is not an @Indexed entity: " + entityType.getName();
+ throw new IllegalArgumentException( msg );
+ }
- if ( searchFactoryImplementor.getDocumentBuilder( entityType ) == null
- && searchFactoryImplementor.getContainedInOnlyBuilder( entityType ) == null ) {
- throw new IllegalArgumentException( "Entity to index is not an @Indexed entity nor @ContainedIn another entity: "
- + entityType.getName() );
- }
- WorkType type;
+ Work work;
if ( id == null ) {
- type = WorkType.PURGE_ALL;
+ // purge the main entity
+ work = new Work( entityType, id, WorkType.PURGE_ALL );
+ searchFactoryImplementor.getWorker().performWork( work, transactionContext );
+
+ // purge the subclasses
+ Set<Class<?>> subClasses = builder.getMappedSubclasses();
+ for ( Class clazz : subClasses ) {
+ work = new Work( clazz, id, WorkType.PURGE_ALL );
+ searchFactoryImplementor.getWorker().performWork( work, transactionContext );
+ }
}
else {
- type = WorkType.PURGE;
+ work = new Work( entityType, id, WorkType.PURGE );
+ searchFactoryImplementor.getWorker().performWork( work, transactionContext );
}
- Work work = new Work( entityType, id, type );
- searchFactoryImplementor.getWorker().performWork( work, transactionContext );
}
/**
@@ -134,19 +140,21 @@
* The entity must be associated with the session
*
* @param entity The entity to index - must not be <code>null</code>.
+ *
* @throws IllegalArgumentException if entity is null or not an @Indexed entity
*/
public void index(Object entity) {
- if ( entity == null ) throw new IllegalArgumentException( "Entity to index should not be null" );
+ if ( entity == null ) {
+ throw new IllegalArgumentException( "Entity to index should not be null" );
+ }
Class<?> clazz = Hibernate.getClass( entity );
//TODO cache that at the FTSession level
SearchFactoryImplementor searchFactoryImplementor = getSearchFactoryImplementor();
//not strictly necessary but a small optimization
- if ( searchFactoryImplementor.getDocumentBuilder( clazz ) == null
- && searchFactoryImplementor.getContainedInOnlyBuilder( clazz ) == null ) {
- throw new IllegalArgumentException( "Entity to index is not an @Indexed entity nor @ContainedIn another entity: "
- + entity.getClass().getName() );
+ if ( searchFactoryImplementor.getDocumentBuilder( clazz ) == null ) {
+ String msg = "Entity to index is not an @Indexed entity: " + entity.getClass().getName();
+ throw new IllegalArgumentException( msg );
}
Serializable id = session.getIdentifier( entity );
Work work = new Work( entity, id, WorkType.INDEX );
@@ -203,7 +211,8 @@
return session.filter( collection, filter, value, type );
}
- public Collection filter(Object collection, String filter, Object[] values, Type[] types) throws HibernateException {
+ public Collection filter(Object collection, String filter, Object[] values, Type[] types)
+ throws HibernateException {
return session.filter( collection, filter, values, types );
}
Modified: search/trunk/src/test/org/hibernate/search/test/SearchTestCase.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/SearchTestCase.java 2008-10-24 14:00:30 UTC (rev 15385)
+++ search/trunk/src/test/org/hibernate/search/test/SearchTestCase.java 2008-10-24 14:22:27 UTC (rev 15386)
@@ -36,7 +36,6 @@
}
protected void setUp() throws Exception {
-// super.setUp(); //we need a fresh session factory each time for index set up
buildSessionFactory( getMappings(), getAnnotatedPackages(), getXmlFiles() );
}
Modified: search/trunk/src/test/org/hibernate/search/test/inheritance/InheritanceTest.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/inheritance/InheritanceTest.java 2008-10-24 14:00:30 UTC (rev 15385)
+++ search/trunk/src/test/org/hibernate/search/test/inheritance/InheritanceTest.java 2008-10-24 14:22:27 UTC (rev 15386)
@@ -1,77 +1,124 @@
//$Id$
package org.hibernate.search.test.inheritance;
-import org.hibernate.search.test.SearchTestCase;
-import org.hibernate.search.FullTextSession;
-import org.hibernate.search.Search;
-import org.hibernate.Transaction;
+import java.util.List;
+
+import org.apache.lucene.analysis.StopAnalyzer;
+import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.QueryParser;
-import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
-import org.apache.lucene.index.Term;
-import java.util.List;
+import org.hibernate.Transaction;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.test.SearchTestCase;
/**
* @author Emmanuel Bernard
*/
public class InheritanceTest extends SearchTestCase {
+ protected void setUp() throws Exception {
+ super.setUp();
+ ensureIndexesAreEmpty();
+ }
+
public void testInheritance() throws Exception {
+ createTestData();
FullTextSession s = Search.getFullTextSession( openSession() );
Transaction tx = s.beginTransaction();
- Animal a = new Animal();
- a.setName("Shark Jr");
- s.save( a );
- Mammal m = new Mammal();
- m.setMammalNbr(2);
- m.setName("Elephant Jr");
- m.setWeight( 400 );
- s.save(m);
- tx.commit();//post commit events for lucene
- s.clear();
- tx = s.beginTransaction();
- QueryParser parser = new QueryParser("name", new StopAnalyzer() );
+ QueryParser parser = new QueryParser( "name", new StopAnalyzer() );
Query query;
org.hibernate.Query hibQuery;
- query = parser.parse( "Elephant" );
+ query = parser.parse( "Elephant" );
hibQuery = s.createFullTextQuery( query, Mammal.class );
List result = hibQuery.list();
assertNotNull( result );
assertEquals( "Query subclass by superclass attribute", 1, result.size() );
- query = parser.parse( "mammalNbr:[2 TO 2]" );
+ query = parser.parse( "mammalNbr:[2 TO 2]" );
hibQuery = s.createFullTextQuery( query, Animal.class, Mammal.class );
result = hibQuery.list();
assertNotNull( result );
assertEquals( "Query subclass by subclass attribute", 1, result.size() );
- query = parser.parse( "Jr" );
+ query = parser.parse( "Jr" );
hibQuery = s.createFullTextQuery( query, Animal.class );
result = hibQuery.list();
assertNotNull( result );
assertEquals( "Query filtering on superclass return mapped subclasses", 2, result.size() );
- query = new RangeQuery( new Term( "weight", "00200" ), null, true);
+ query = new RangeQuery( new Term( "weight", "00200" ), null, true );
hibQuery = s.createFullTextQuery( query, Animal.class );
result = hibQuery.list();
assertNotNull( result );
assertEquals( "Query on non @Indexed superclass property", 1, result.size() );
- for (Object managedEntity : result) {
- s.delete(managedEntity);
- }
- tx.commit();
+ tx.commit();
s.close();
}
+ /**
+ * Tests that purging the index of a class also purges the index of the subclasses. See also HSEARCH-262.
+ *
+ * @throws Exception in case the test fails.
+ */
+ public void testPurgeIndex() throws Exception {
+ createTestData();
+ FullTextSession s = Search.getFullTextSession( openSession() );
+ Transaction tx = s.beginTransaction();
+ QueryParser parser = new QueryParser( "name", new StopAnalyzer() );
+
+ Query query = parser.parse( "Jr" );
+ List result = s.createFullTextQuery( query, Animal.class ).list();
+ assertNotNull( result );
+ assertEquals( "Wrong number of hits. There should be one elephant and one shark.", 2, result.size() );
+
+ s.purgeAll( Animal.class );
+ tx.commit();
+ tx = s.beginTransaction();
+ result = s.createFullTextQuery( query, Animal.class ).list();
+ assertNotNull( result );
+ assertEquals(
+ "Wrong number of hits. Purging the Animal class should also purge the Mammals", 0, result.size()
+ );
+
+ tx.commit();
+
+ s.close();
+ }
+
+ private void createTestData() {
+ FullTextSession s = Search.getFullTextSession( openSession() );
+ Transaction tx = s.beginTransaction();
+ Animal a = new Animal();
+ a.setName( "Shark Jr" );
+ s.save( a );
+ Mammal m = new Mammal();
+ m.setMammalNbr( 2 );
+ m.setName( "Elephant Jr" );
+ m.setWeight( 400 );
+ s.save( m );
+ tx.commit();//post commit events for lucene
+ s.clear();
+ }
+
+ private void ensureIndexesAreEmpty() {
+ FullTextSession s = Search.getFullTextSession( openSession() );
+ Transaction tx;
+ tx = s.beginTransaction();
+ s.purgeAll( Animal.class );
+ s.purgeAll( Mammal.class );
+ tx.commit();
+ }
+
protected Class[] getMappings() {
return new Class[] {
- Animal.class,
- Mammal.class
- };
+ Animal.class,
+ Mammal.class
+ };
}
}
More information about the hibernate-commits
mailing list