org.hibernate.search.test.query.LuceneQueryTest.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.search.test.query.LuceneQueryTest.java

Source

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat, Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.hibernate.search.test.query;

import java.util.Iterator;
import java.util.List;

import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;

import org.hibernate.FetchMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Transaction;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.test.SearchTestCase;
import org.hibernate.search.util.impl.HibernateHelper;
import org.hibernate.stat.Statistics;

/**
 * @author Emmanuel Bernard
 * @author John Griffin
 * @author Hardy Ferentschik
 */
public class LuceneQueryTest extends SearchTestCase {

    public void testList() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Clock clock = new Clock(1, "Seiko");
        s.save(clock);
        clock = new Clock(2, "Festina");
        s.save(clock);
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        book = new Book(2, "La gloire de mon pre", "Les deboires de mon pre en vlo");
        s.save(book);
        tx.commit();
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:noword");
        org.hibernate.Query hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        List result = hibQuery.list();
        assertNotNull(result);
        assertEquals(0, result.size());

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with explicit class filter", 2, result.size());

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query, Clock.class);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with one class filter", 1, result.size());

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with no class filter", 2, result.size());
        for (Object element : result) {
            assertTrue(HibernateHelper.isInitialized(element));
            s.delete(element);
        }
        s.flush();
        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with delete objects", 0, result.size());

        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testResultSize() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Clock clock = new Clock(1, "Seiko");
        s.save(clock);
        clock = new Clock(2, "Festina");
        s.save(clock);
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        book = new Book(2, "La gloire de mon pre", "Les deboires de mon pre en vlo");
        s.save(book);
        tx.commit();
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:Festina Or brand:Seiko");
        Statistics stats = s.getSessionFactory().getStatistics();
        stats.clear();
        boolean enabled = stats.isStatisticsEnabled();
        if (!enabled) {
            stats.setStatisticsEnabled(true);
        }
        FullTextQuery hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        assertEquals("Exection of getResultSize without actual results", 2, hibQuery.getResultSize());
        assertEquals("No entity should be loaded", 0, stats.getEntityLoadCount());

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query);
        List result = hibQuery.list();
        assertNotNull(result);
        assertEquals("2 entities should be loaded", 2, stats.getEntityLoadCount());
        if (!enabled) {
            stats.setStatisticsEnabled(false);
        }
        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testFirstMax() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Clock clock = new Clock(1, "Seiko");
        s.save(clock);
        clock = new Clock(2, "Festina");
        s.save(clock);
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        book = new Book(2, "La gloire de mon pre", "Les deboires de mon pre en vlo");
        s.save(book);
        tx.commit();
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:Festina Or brand:Seiko");
        org.hibernate.Query hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        hibQuery.setFirstResult(1);
        List result = hibQuery.list();
        assertNotNull(result);
        assertEquals("first result no max result", 1, result.size());

        hibQuery.setFirstResult(0);
        hibQuery.setMaxResults(1);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("max result set", 1, result.size());

        hibQuery.setFirstResult(0);
        hibQuery.setMaxResults(3);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("max result out of limit", 2, result.size());

        hibQuery.setFirstResult(2);
        hibQuery.setMaxResults(3);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("first result out of limit", 0, result.size());

        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testIterator() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Clock clock = new Clock(1, "Seiko");
        s.save(clock);
        clock = new Clock(2, "Festina");
        s.save(clock);
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        book = new Book(2, "La gloire de mon pre", "Les deboires de mon pre en vlo");
        s.save(book);
        tx.commit();//post commit events for lucene
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:noword");
        org.hibernate.Query hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        Iterator result = hibQuery.iterate();
        assertNotNull(result);
        assertFalse(result.hasNext());

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        result = hibQuery.iterate();
        assertNotNull(result);
        int index = 0;
        while (result.hasNext()) {
            index++;
            s.delete(result.next());
        }
        assertEquals(2, index);

        s.flush();

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        result = hibQuery.iterate();
        assertNotNull(result);
        assertFalse(result.hasNext());

        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testScrollableResultSet() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Clock clock = new Clock(1, "Seiko");
        s.save(clock);
        clock = new Clock(2, "Festina");
        s.save(clock);
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        book = new Book(2, "La gloire de mon pre", "Les deboires de mon pre en vlo");
        s.save(book);
        tx.commit();//post commit events for lucene
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:noword");
        org.hibernate.Query hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        ScrollableResults result = hibQuery.scroll();
        assertNotNull(result);
        assertEquals(-1, result.getRowNumber());
        assertEquals(false, result.next());
        result.close();

        query = parser.parse("summary:Festina Or brand:Seiko");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        result = hibQuery.scroll();
        assertEquals(-1, result.getRowNumber());
        result.beforeFirst();
        assertEquals(true, result.next());
        assertTrue(result.isFirst());
        assertTrue(result.scroll(1));
        assertTrue(result.isLast());
        assertFalse(result.scroll(1));
        result.beforeFirst();
        while (result.next()) {
            s.delete(result.get()[0]);
        }
        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    // Technically this is checked by other tests but let's do it anyway. J.G.

    public void testDefaultFetchSize() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:ITech");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setProjection("id", "lastname", "dept");

        ScrollableResults projections = hibQuery.scroll();
        projections.beforeFirst();
        Object[] projection = projections.get();
        assertNull(projection);

        projections.next();
        assertTrue(projections.isFirst());

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testFetchSizeLargerThanHits() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:ITech");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setProjection("id", "lastname", "dept");
        hibQuery.setFetchSize(6);

        ScrollableResults results = hibQuery.scroll();
        results.beforeFirst();
        results.next();
        Object[] result = results.get();
        assertEquals("incorrect entityInfo returned", 1000, result[0]);

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testFetchSizeDefaultFirstAndMax() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:ITech");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setSort(new Sort(new SortField("id", SortField.STRING)));
        hibQuery.setProjection("id", "lastname", "dept");
        hibQuery.setFetchSize(3);

        ScrollableResults results = hibQuery.scroll();
        results.beforeFirst();
        results.next();
        Object[] result = results.get();
        assertEquals("incorrect entityInfo returned", 1000, result[0]);
        results.scroll(2);
        result = results.get();
        assertEquals("incorrect entityInfo returned", 1003, result[0]);
        // check cache addition
        results.next();
        result = results.get();
        assertEquals("incorrect entityInfo returned", 1004, result[0]);

        results.scroll(-2);
        result = results.get();
        assertEquals("incorrect entityInfo returned", 1002, result[0]);

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testFetchSizeNonDefaultFirstAndMax() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:ITech");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setProjection("id", "lastname", "dept");
        hibQuery.setFetchSize(3);
        hibQuery.setFirstResult(1);
        hibQuery.setMaxResults(3);
        hibQuery.setSort(new Sort(new SortField("id", SortField.STRING)));

        ScrollableResults results = hibQuery.scroll();
        results.beforeFirst();
        results.next();
        Object[] result = results.get();
        assertEquals("incorrect entityInfo returned", 1002, result[0]);

        results.scroll(2);
        result = results.get();
        assertEquals("incorrect entityInfo returned", 1004, result[0]);

        results.next();
        result = results.get();
        assertNull(result);

        results.scroll(-8);
        result = results.get();
        assertNull(result);

        // And test a bad forward scroll.
        results.scroll(10);
        result = results.get();
        assertNull(result);

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testFetchSizeNonDefaultFirstAndMaxNoHits() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:XXX");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setProjection("id", "lastname", "dept");
        hibQuery.setFetchSize(3);
        hibQuery.setFirstResult(1);
        hibQuery.setMaxResults(3);

        ScrollableResults results = hibQuery.scroll();
        results.beforeFirst();
        Object[] result = results.get();
        assertNull("non-null entity infos returned", result);

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    /**
     * Test for HSEARCH-604. Tests that max result 0 does not throw an exception.
     *
     * @throws Exception in case the test fails.
     */
    public void testMaxResultZero() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);
        Query query = parser.parse("dept:foo");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setFirstResult(0);
        hibQuery.setMaxResults(0);

        List result = hibQuery.list();
        assertTrue("We should get the empty result list", result.isEmpty());

        hibQuery.setFirstResult(1);
        hibQuery.setMaxResults(0);

        result = hibQuery.list();
        assertTrue("We should get the empty result list", result.isEmpty());

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testCurrent() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:ITech");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        hibQuery.setProjection("id", "lastname", "dept");

        ScrollableResults results = hibQuery.scroll();
        results.beforeFirst();
        results.next();
        assertTrue("beforeFirst() pointer incorrect", results.isFirst());

        results.afterLast();
        results.previous();
        assertTrue("afterLast() pointer incorrect", results.isLast());

        // Let's see if a bad reverse scroll screws things up
        results.scroll(-8);
        results.next();
        assertTrue("large negative scroll() pointer incorrect", results.isFirst());

        // And test a bad forward scroll.
        results.scroll(10);
        results.previous();
        assertTrue("large positive scroll() pointer incorrect", results.isLast());

        // Finally, let's test a REAL screwup.
        hibQuery.setFirstResult(3);
        hibQuery.setMaxResults(1);

        results = hibQuery.scroll();
        results.first();
        Object[] result = results.get();
        assertEquals(1004, result[0]);

        results.last();
        result = results.get();
        assertEquals(1004, result[0]);

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testMultipleEntityPerIndex() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Clock clock = new Clock(1, "Seiko");
        s.save(clock);
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        AlternateBook alternateBook = new AlternateBook(1,
                "La chute de la petite reine a travers les yeux de Festina");
        s.save(alternateBook);
        tx.commit();
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:Festina");
        org.hibernate.Query hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        List result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with explicit class filter", 1, result.size());

        query = parser.parse("summary:Festina");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        Iterator it = hibQuery.iterate();
        assertTrue(it.hasNext());
        assertNotNull(it.next());
        assertFalse(it.hasNext());

        query = parser.parse("summary:Festina");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        ScrollableResults sr = hibQuery.scroll();
        assertTrue(sr.first());
        assertNotNull(sr.get());
        assertFalse(sr.next());
        sr.close();

        query = parser.parse("summary:Festina OR brand:seiko");
        hibQuery = s.createFullTextQuery(query, Clock.class, Book.class);
        hibQuery.setMaxResults(2);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with explicit class filter and limit", 2, result.size());

        query = parser.parse("summary:Festina");
        hibQuery = s.createFullTextQuery(query);
        result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with no class filter", 2, result.size());
        for (Object element : result) {
            assertTrue(HibernateHelper.isInitialized(element));
            s.delete(element);
        }
        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testCriteria() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        Transaction tx = s.beginTransaction();
        Book book = new Book(1, "La chute de la petite reine a travers les yeux de Festina",
                "La chute de la petite reine a travers les yeux de Festina, blahblah");
        s.save(book);
        Author emmanuel = new Author();
        emmanuel.setName("Emmanuel");
        s.save(emmanuel);
        book.getAuthors().add(emmanuel);
        tx.commit();
        s.clear();
        tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "title", SearchTestCase.stopAnalyzer);

        Query query = parser.parse("summary:Festina");
        org.hibernate.Query hibQuery = s.createFullTextQuery(query, Book.class);
        List result = hibQuery.list();
        assertNotNull(result);
        assertEquals("Query with no explicit criteria", 1, result.size());
        book = (Book) result.get(0);
        assertFalse("Association should not be inintialized", HibernateHelper.isInitialized(book.getAuthors()));

        result = s.createFullTextQuery(query)
                .setCriteriaQuery(s.createCriteria(Book.class).setFetchMode("authors", FetchMode.JOIN)).list();
        assertNotNull(result);
        assertEquals("Query with explicit criteria", 1, result.size());
        book = (Book) result.get(0);
        assertTrue("Association should be inintialized", HibernateHelper.isInitialized(book.getAuthors()));
        assertEquals(1, book.getAuthors().size());

        //cleanup
        Author author = book.getAuthors().iterator().next();
        book.getAuthors().remove(author);

        for (Object element : s.createQuery("from java.lang.Object").list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testScrollEmptyHits() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:XXX");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);

        ScrollableResults projections = hibQuery.scroll();
        projections.beforeFirst();
        projections.next();
        Object[] projection = projections.get();
        assertNull(projection);

        hibQuery = s.createFullTextQuery(query, Employee.class).setFirstResult(10).setMaxResults(20);

        projections = hibQuery.scroll();
        projections.beforeFirst();
        projections.next();
        projection = projections.get();
        assertNull(projection);

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testListEmptyHits() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:XXX");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        List result = hibQuery.list();
        assertEquals(0, result.size());

        hibQuery = s.createFullTextQuery(query, Employee.class).setFirstResult(10).setMaxResults(20);
        result = hibQuery.list();
        assertEquals(0, result.size());

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    public void testIterateEmptyHits() throws Exception {
        FullTextSession s = Search.getFullTextSession(openSession());
        prepEmployeeIndex(s);

        s.clear();
        Transaction tx = s.beginTransaction();
        QueryParser parser = new QueryParser(getTargetLuceneVersion(), "dept", SearchTestCase.standardAnalyzer);

        Query query = parser.parse("dept:XXX");
        org.hibernate.search.FullTextQuery hibQuery = s.createFullTextQuery(query, Employee.class);
        Iterator iter = hibQuery.iterate();
        assertFalse(iter.hasNext());

        hibQuery = s.createFullTextQuery(query, Employee.class).setFirstResult(10).setMaxResults(20);
        iter = hibQuery.iterate();
        assertFalse(iter.hasNext());

        //cleanup
        for (Object element : s.createQuery("from " + Employee.class.getName()).list()) {
            s.delete(element);
        }
        tx.commit();
        s.close();
    }

    private void prepEmployeeIndex(FullTextSession s) {
        Transaction tx = s.beginTransaction();
        s.save(new Employee(1000, "Griffin", "ITech"));
        s.save(new Employee(1001, "Jackson", "Accounting"));
        s.save(new Employee(1002, "Jimenez", "ITech"));
        s.save(new Employee(1003, "Stejskal", "ITech"));
        s.save(new Employee(1004, "Whetbrook", "ITech"));
        tx.commit();
    }

    protected Class<?>[] getAnnotatedClasses() {
        return new Class[] { Book.class, AlternateBook.class, Clock.class, Author.class, Employee.class };
    }
}