packageentity;importjava.util.List;importjavax.persistence.EntityManager;importjavax.persistence.EntityManagerFactory;importjavax.persistence.NoResultException;importjavax.persistence.NonUniqueResultException;importjavax.persistence.Persistence;importorg.apache.log4j.BasicConfigurator;importorg.apache.log4j.Level;importorg.apache.log4j.Logger;importorg.hibernate.hql.ast.QuerySyntaxException;importorg.junit.After;importorg.junit.Assert;importorg.junit.Before;importorg.junit.BeforeClass;importorg.junit.Test;publicclassQueriesTestextendsAssert{privateEntityManagerFactoryemf;privateEntityManagerem;@BeforeClasspublicstaticvoidinitLogger(){// Produce minimal output.BasicConfigurator.configure();// Comment this line to see a lot of initialization// status logging.Logger.getLogger("org").setLevel(Level.ERROR);}@BeforepublicvoidinitEmfAndEm(){emf=Persistence.createEntityManagerFactory("examplePersistenceUnit");em=emf.createEntityManager();}@AfterpublicvoidcloseEmAndEmf(){em.close();emf.close();}@Test(expected=IllegalArgumentException.class)publicvoidunsuccessfulWithBadExceptionThrownEmptyQuery(){Logger.getLogger("org").setLevel(Level.FATAL);try{// This one got me and I wasted several hours looking at// the wrong rabbit hole. I was paying attention to the// error but not looking at the line that was failing.em.createQuery("");}finally{Logger.getLogger("org").setLevel(Level.ERROR);}}@TestpublicvoidunsuccessfulUnknownClass(){try{// This fails because IncorrectClassName is not registered.// If we were using JEE rather than JSE, this implies that// there is no class named IncorrectClassName anywhere// in the class path that has the @Entity annotation (or// is mapped via XML).em.createQuery("from IncorrectClassName");}catch(IllegalArgumentExceptione){assertEquals(e.getCause().getClass(),QuerySyntaxException.class);assertEquals(("org.hibernate.hql.ast.QuerySyntaxException: "+"IncorrectClassName is not mapped "+"[from IncorrectClassName]"),e.getMessage());}}@TestpublicvoidsuccessfulNotUsingSelect(){em.createQuery("from Person").getResultList();}@TestpublicvoidsuccessfulSingleResult(){clearPersonTable();insertPerson();// This query has the potential to fail since it is returning// all Person entities, but it does not because I've only// inserted one.finalPersonp=(Person)em.createQuery("from Person").getSingleResult();assertEquals("Brett",p.getFirstName());}@Test(expected=NoResultException.class)publicvoidunsuccessfulSingleResultNoEntries(){// Notice that if we just want to get all rows from// an Entity's table, this is the minimal queryem.createQuery("from Person").getSingleResult();}@Test(expected=NonUniqueResultException.class)publicvoidunsuccessfulSingleResultTooManyEntries(){insertPerson();insertPerson();// This will fail because we expect a single result// but in fact there are 2 results returned.em.createQuery("from Person").getSingleResult();}@TestpublicvoidsuccessfulFindByPrimaryKey(){finalintpersonKey=insertPerson();// Note, we provide Person.class as the first parameter// so the underling method, which is a generic method// can return the right type. Also, because we provide// the class, the only thing that might happen is that// we do not find a Person in the Person table. It is// not possible for find to return the wrong type since// it picks up its table name from the Person.class.finalPersonp=em.find(Person.class,personKey);assertEquals("Brett",p.getFirstName());}@TestpublicvoidunsuccessfulLookupByKeyNothingFound(){clearPersonTable();// Note the lack of an "expected = ..." in the @Test// annotation. Find returns null if it cannot find// the object with the provided key. It does not throw// an exception.finalPersonp=em.find(Person.class,-42);assertNull(p);}@TestpublicvoidsuccessfulSearchUsingQueryParameter(){insertPerson();// Note, the return type of this method is List<?>, not List<Person>.// See the next method for the other option...finalList<?>list=em.createQuery("from Person where firstName = ?1").setParameter(1,"Brett").getResultList();assertEquals(1,list.size());}/**
* This method does the same thing as the one above it. But to avoid a
* warning about type safety I am using the annotation
*
* @SuppressWarnings. When you start writing Data Access Objects, you'll
* probably go this route.
*
* For those of you who know generic parameters, it is not possible to get
* this to work in a type-safe manner due to "erasure." Look up "java
* generics erasure".
* http://today.java.net/pub/a/today/2003/12/02/explorations.html
*/@SuppressWarnings("unchecked")@TestpublicvoidtheOtherOption(){insertPerson();finalList<Person>list=em.createQuery("from Person where firstName = ?1").setParameter(1,"Brett").getResultList();assertEquals(1,list.size());}@TestpublicvoidsuccessfulSameInMemoryObjectsReturnedFromDifferntQueries(){finalintpersonKey=insertPerson();finalPersonpByKey=em.find(Person.class,personKey);finalPersonpByWhere=(Person)em.createQuery("SELECT p from Person p where firstName='Brett'").getSingleResult();// are these objects == (same object in memory)?assertSame(pByKey,pByWhere);}@Test(expected=IllegalArgumentException.class)publicvoidunsuccessfulCaseWrongOnClass(){// fails because we're naming a class, not a table// So instead of PERSON we must use Personem.createQuery("from PERSON").getSingleResult();}@Test(expected=IllegalArgumentException.class)publicvoidunsuccessfulWrongFieldNameUsedInWhereWithNamedPerson(){insertPerson();// failes because the attribute is not called FirstName but// is instead called firstName (first letter should be// lower case following the java beans standard.em.createQuery("from Person p where p.FirstName='Brett'");}@TestpublicvoidsuccessfulColumnNameNotCaseSensitive(){insertPerson();// Note that we are not qualifying FirstName with p,// so it is interpreted as a column name rather than// a fieldName that must follow java beans naming// conventionsem.createQuery("from Person p where FirstName='Brett'").getResultList();}@Test(expected=IllegalArgumentException.class)publicvoidunsuccessfulSettingParamterWithWrongIndex(){// Indexes are 1-based, not 0-based.em.createQuery("from Person p where FirstName='Brett'").setParameter(0,"Brett");}@Test(expected=IllegalArgumentException.class)publicvoidunsuccessfulSettingParameterWhereThereAreNone(){// There's no parameter here, this simply failsem.createQuery("from Person p where FirstName='Brett'").setParameter(1,"Brett");}@Test(expected=IllegalArgumentException.class)publicvoidunsuccessfulDoNotQuoteStringParameters(){em.createQuery("from Person p where FirstName='?1'").setParameter(1,"Brett");}/**
* Even though we **begin** a transaction, we never commit it. So when we
* close the em, nothing that was flushed will actually be committed.
*
*/privateintinsertPerson(){finalAddressa1=newAddress("A Rd.","","Dallas","TX","75001");finalPersonp1=newPerson("Brett",'L',"Schuchert",a1);if(!em.getTransaction().isActive()){em.getTransaction().begin();}em.persist(p1);returnp1.getId();}privatevoidclearPersonTable(){if(!em.getTransaction().isActive()){em.getTransaction().begin();}em.createQuery("delete from Person").executeUpdate();}}
Comments