[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