/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.test.query; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.util.Iterator; import java.util.List; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import org.apache.lucene.index.Term; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.search.FullTextQuery; import org.hibernate.search.FullTextSession; import org.hibernate.search.Search; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Indexed; import org.hibernate.search.engine.ProjectionConstants; import org.hibernate.search.exception.AssertionFailure; import org.hibernate.search.test.SearchTestBase; import org.hibernate.search.testsupport.TestForIssue; import org.junit.Before; import org.junit.Test; /** * Tests all kinds of loading when the entities have public fields. * * We take care to test all of those because they trigger different kinds of loading: * <ul> * <li>Single result or multiple results * <li>Single class or multiple classes * <li>list() without projection, list() with THIS projection, or iterate() * </ul> * * @author Yoann Rodiere */ @TestForIssue(jiraKey = "HSEARCH-2541") public class ObjectLoadingPublicFieldTest extends SearchTestBase { private Query fieldFooQuery; private Query fieldBarQuery; @Before @Override public void setUp() throws Exception { super.setUp(); try ( Session session = openSession() ) { Transaction tx = session.beginTransaction(); // used for the filtering tests A a1 = new A(); a1.id = 1L; a1.field = "foo"; B b = new B(); b.id = 2L; b.field = "foo"; C c = new C(); c.id = 3L; c.field = "foo"; session.persist( a1 ); session.persist( b ); session.persist( c ); // used for the not found test A a2 = new A(); a2.id = 4L; a2.field = "bar"; session.persist( a2 ); tx.commit(); } fieldFooQuery = new TermQuery( new Term( "field", "foo" ) ); fieldBarQuery = new TermQuery( new Term( "field", "bar" ) ); } @Test public void singleClass_singleResult() throws Exception { Session session = openSession(); Transaction tx = session.beginTransaction(); FullTextSession fullTextSession = Search.getFullTextSession( session ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class ); List<?> result = fullTextQuery.list(); assertEquals( "Should match B only", 1, result.size() ); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class ) .setProjection( ProjectionConstants.THIS ); result = fullTextQuery.list(); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class ); assertPopulated( fullTextQuery.iterate() ); tx.commit(); fullTextSession.close(); } @Test public void singleClass_multipleResults() throws Exception { Session session = openSession(); Transaction tx = session.beginTransaction(); Query luceneQuery = new MatchAllDocsQuery(); FullTextSession fullTextSession = Search.getFullTextSession( session ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, A.class ); List<?> result = fullTextQuery.list(); assertEquals( "Should match A only", 2, result.size() ); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, A.class ) .setProjection( ProjectionConstants.THIS ); result = fullTextQuery.list(); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, A.class ); assertPopulated( fullTextQuery.iterate() ); tx.commit(); fullTextSession.close(); } @Test public void twoClasses_singleResult() throws Exception { Session session = openSession(); Transaction tx = session.beginTransaction(); FullTextSession fullTextSession = Search.getFullTextSession( session ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( fieldBarQuery, A.class, B.class ); List<?> result = fullTextQuery.list(); assertEquals( "Should match a single A only", 1, result.size() ); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldBarQuery, A.class, B.class ) .setProjection( ProjectionConstants.THIS ); result = fullTextQuery.list(); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldBarQuery, A.class, B.class ); assertPopulated( fullTextQuery.iterate() ); tx.commit(); fullTextSession.close(); } @Test public void twoClasses_multipleResults() throws Exception { Session session = openSession(); Transaction tx = session.beginTransaction(); FullTextSession fullTextSession = Search.getFullTextSession( session ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class, B.class ); List<?> result = fullTextQuery.list(); assertEquals( "Should match A and B only", 2, result.size() ); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class, B.class ) .setProjection( ProjectionConstants.THIS ); result = fullTextQuery.list(); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class, B.class ); assertPopulated( fullTextQuery.iterate() ); tx.commit(); fullTextSession.close(); } @Test public void threeClasses() throws Exception { Session session = openSession(); Transaction tx = session.beginTransaction(); FullTextSession fullTextSession = Search.getFullTextSession( session ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class, B.class, C.class ); List<?> result = fullTextQuery.list(); assertEquals( "Should match all types", 3, result.size() ); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery, A.class, B.class, C.class ) .setProjection( ProjectionConstants.THIS ); result = fullTextQuery.list(); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery ); assertPopulated( fullTextQuery.iterate() ); tx.commit(); fullTextSession.close(); } @Test public void implicitAllClasses() throws Exception { Session session = openSession(); Transaction tx = session.beginTransaction(); FullTextSession fullTextSession = Search.getFullTextSession( session ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery ); List<?> result = fullTextQuery.list(); assertEquals( "Should match all types", 3, result.size() ); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery ) .setProjection( ProjectionConstants.THIS ); result = fullTextQuery.list(); assertPopulated( result ); fullTextSession.clear(); fullTextQuery = fullTextSession.createFullTextQuery( fieldFooQuery ); assertPopulated( fullTextQuery.iterate() ); tx.commit(); fullTextSession.close(); } private void assertPopulated(Iterator<?> iterator) { while ( iterator.hasNext() ) { Object result = iterator.next(); assertPopulated( result ); } } private void assertPopulated(List<?> results) { for ( Object result : results ) { assertPopulated( result ); } } private void assertPopulated(Object result) { if ( result instanceof Object[] ) { Object[] tuple = (Object[]) result; if ( tuple.length != 1 ) { throw new AssertionFailure( "Unexpected tuple size for result " + result ); } result = tuple[0]; } if ( result instanceof A ) { assertNotNull( ((A) result).id ); } else if ( result instanceof B ) { assertNotNull( ((B) result).id ); } else if ( result instanceof C ) { assertNotNull( ((C) result).id ); } else { throw new AssertionFailure( "Unexpected type for result " + result ); } } @Override public Class<?>[] getAnnotatedClasses() { return new Class[] { A.class, B.class, C.class }; } @Entity @Table(name = "A") @Indexed private static class A { protected A() { } @Id public Long id; @Field public String field; } @Entity @Indexed private static class B { protected B() { } @Id public Long id; @Field public String field; } @Entity @Indexed private static class C { protected C() { } @Id public Long id; @Field public String field; } }