//$Id
package org.hibernate.search.test.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.hibernate.ScrollableResults;
import org.hibernate.Transaction;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.test.util.FullTextSessionBuilder;
import junit.framework.TestCase;
/**
* Test for org.hibernate.search.query.ScrollableResultsImpl
*
* @see org.hibernate.search.query.ScrollableResultsImpl
* @author Sanne Grinovero
*/
public class ScrollableResultsTest extends TestCase {
private FullTextSessionBuilder builder;
private FullTextSession sess;
@Override
public void setUp() throws Exception {
super.setUp();
builder = new FullTextSessionBuilder();
sess = builder
.addAnnotatedClass( AlternateBook.class )
.addAnnotatedClass( Employee.class )
.setProperty( "hibernate.default_batch_fetch_size", "10" )
.build();
Transaction tx = sess.beginTransaction();
//create some entities to query:
for ( int i = 0; i < 324; i++ ) {
sess.persist( new AlternateBook( i , "book about the number " + i ) );
}
for ( int i = 0; i < 133; i++ ) {
sess.persist( new Employee( i , "Rossi", "dept. num. " + i ) );
}
tx.commit();
}
@Override
protected void tearDown() throws Exception {
builder.close();
super.tearDown();
}
/**
* Test forward scrolling using pagination
*/
public void testScrollingForward() {
Transaction tx = sess.beginTransaction();
TermQuery tq = new TermQuery( new Term( "summary", "number") );
Sort sort = new Sort( new SortField( "summary" ) );
ScrollableResults scrollableResults = sess
.createFullTextQuery( tq, AlternateBook.class )
.setSort( sort )
.setFetchSize( 10 )
.setFirstResult( 20 )
.setMaxResults( 111 )
.scroll();
assertEquals( -1, scrollableResults.getRowNumber() );
assertTrue( scrollableResults.last() );
assertEquals( 110, scrollableResults.getRowNumber() );
scrollableResults.beforeFirst();
int position = scrollableResults.getRowNumber();
while ( scrollableResults.next() ) {
position++;
int bookId = position + 20;
assertEquals( position, scrollableResults.getRowNumber() );
AlternateBook book = (AlternateBook) scrollableResults.get()[0];
assertEquals( bookId, book.getId().intValue() );
assertEquals( "book about the number " + bookId, book.getSummary() );
assertTrue( sess.contains( book ) );
}
assertEquals( 110, position );
scrollableResults.close();
tx.commit();
}
/**
* Verify inverse-order scrolling.
* TODO to verify correct FetchSize behavior I've been debugging
* the behavior; we should add a mock library to automate this kind of tests.
*/
public void testScrollingBackwards() {
Transaction tx = sess.beginTransaction();
TermQuery tq = new TermQuery( new Term( "summary", "number") );
Sort sort = new Sort( new SortField( "summary" ) );
ScrollableResults scrollableResults = sess
.createFullTextQuery( tq, AlternateBook.class )
.setSort( sort )
.setFetchSize( 10 )
.scroll();
scrollableResults.beforeFirst();
// initial position should be -1 as in Hibernate Core
assertEquals( -1, scrollableResults.getRowNumber() );
assertTrue( scrollableResults.last() );
int position = scrollableResults.getRowNumber();
assertEquals( 323, position );
while ( scrollableResults.previous() ) {
AlternateBook book = (AlternateBook) scrollableResults.get()[0];
assertEquals( --position, book.getId().intValue() );
assertEquals( "book about the number " + position, book.getSummary() );
}
assertEquals( 0, position );
assertEquals( -1, scrollableResults.getRowNumber() );
scrollableResults.close();
tx.commit();
}
/**
* Test that all entities returned by a ScrollableResults
* are always attached to Session
*/
public void testResultsAreManaged() {
Transaction tx = sess.beginTransaction();
TermQuery tq = new TermQuery( new Term( "summary", "number") );
Sort sort = new Sort( new SortField( "summary" ) );
ScrollableResults scrollableResults = sess
.createFullTextQuery( tq, AlternateBook.class )
.setSort( sort )
.setFetchSize( 10 )
.scroll();
int position = -1;
while ( scrollableResults.next() ) {
position++;
AlternateBook book = (AlternateBook) scrollableResults.get()[0];
assertTrue( sess.contains( book ) );
// evict some entities:
if ( position % 3 == 0 ) {
sess.evict( book );
assertFalse( sess.contains( book ) );
}
}
//verifies it did scroll to the end:
assertEquals( 323, position );
//assert the entities are re-attached after eviction:
while ( scrollableResults.previous() ) {
position--;
AlternateBook book = (AlternateBook) scrollableResults.get()[0];
assertTrue( sess.contains( book ) );
}
assertEquals( -1, position );
sess.clear();
//assert the entities are re-attached after Session.clear:
while ( scrollableResults.next() ) {
position++;
AlternateBook book = (AlternateBook) scrollableResults.get()[0];
assertTrue( sess.contains( book ) );
}
assertEquals( 323, position );
tx.commit();
}
/**
* Verify scrolling works correctly when combined with Projection
* and that the projected entities are managed, even in case
* of evict usage for memory management.
*/
public void testScrollProjectionAndManaged() {
Transaction tx = sess.beginTransaction();
TermQuery tq = new TermQuery( new Term( "dept", "num") );
ScrollableResults scrollableResults = sess
.createFullTextQuery( tq, Employee.class )
.setProjection(
FullTextQuery.OBJECT_CLASS,
FullTextQuery.ID,
FullTextQuery.THIS,
"lastname",
FullTextQuery.THIS
)
.setFetchSize( 10 )
.scroll();
scrollableResults.last();
assertEquals( 132, scrollableResults.getRowNumber() );
scrollableResults.beforeFirst();
assertEquals( -1, scrollableResults.getRowNumber() );
int position = scrollableResults.getRowNumber();
while ( scrollableResults.next() ) {
position++;
Object[] objs = scrollableResults.get();
assertEquals( Employee.class, objs[0] );
assertEquals( position, objs[1] );
assertTrue( objs[2] instanceof Employee );
sess.contains( objs[2] );
assertEquals( "Rossi", objs[3] );
assertTrue( objs[4] instanceof Employee );
sess.contains( objs[4] );
assertTrue( objs[2]==objs[4] ); //projected twice the same entity
// detach some objects:
if ( position%3 == 0 ) {
sess.evict( objs[2] );
}
}
//verify we scrolled to the end:
assertEquals( 132, position );
// and now the other way around, checking entities are attached again:
while ( scrollableResults.previous() ) {
position--;
Object[] objs = scrollableResults.get();
assertTrue( objs[2] instanceof Employee );
sess.contains( objs[2] );
assertTrue( objs[4] instanceof Employee );
sess.contains( objs[4] );
assertTrue( objs[2]==objs[4] );
}
assertEquals( -1, position );
scrollableResults.close();
tx.commit();
}
}