Tutorial+2+-+One+Example+Solution

code format="java5" package entity;

import java.util.List;

import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import javax.persistence.Persistence;

import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.hibernate.hql.ast.QuerySyntaxException; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test;

public class QueriesTest extends Assert { private EntityManagerFactory emf; private EntityManager em;

@BeforeClass public static void initLogger { // Produce minimal output. BasicConfigurator.configure;

// Comment this line to see a lot of initialization // status logging. Logger.getLogger("org").setLevel(Level.ERROR); }

@Before public void initEmfAndEm { emf = Persistence.createEntityManagerFactory("examplePersistenceUnit"); em = emf.createEntityManager; }

@After public void closeEmAndEmf { em.close; emf.close; }

@Test(expected = IllegalArgumentException.class) public void unsuccessfulWithBadExceptionThrownEmptyQuery { 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); }   }

@Test public void unsuccessfulUnknownClass { 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 (IllegalArgumentException e) { assertEquals(e.getCause.getClass, QuerySyntaxException.class); assertEquals(                   ("org.hibernate.hql.ast.QuerySyntaxException: " + "IncorrectClassName is not mapped " + "[from IncorrectClassName]"),                   e.getMessage); }   }

@Test public void successfulNotUsingSelect { em.createQuery("from Person").getResultList; }

@Test public void successfulSingleResult { 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. final Person p = (Person) em.createQuery("from Person") .getSingleResult; assertEquals("Brett", p.getFirstName); }

@Test(expected = NoResultException.class) public void unsuccessfulSingleResultNoEntries { // Notice that if we just want to get all rows from // an Entity's table, this is the minimal query em.createQuery("from Person").getSingleResult; }

@Test(expected = NonUniqueResultException.class) public void unsuccessfulSingleResultTooManyEntries { insertPerson; insertPerson;

// This will fail because we expect a single result // but in fact there are 2 results returned. em.createQuery("from Person").getSingleResult; }

@Test public void successfulFindByPrimaryKey { final int personKey = 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. final Person p = em.find(Person.class, personKey); assertEquals("Brett", p.getFirstName); }

@Test public void unsuccessfulLookupByKeyNothingFound { 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. final Person p = em.find(Person.class, -42); assertNull(p); }

@Test public void successfulSearchUsingQueryParameter { insertPerson;

// Note, the return type of this method is List<?>, not List. // See the next method for the other option... final List<?> 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") @Test public void theOtherOption { insertPerson;

final List list = em.createQuery(               "from Person where firstName = ?1").setParameter(1, "Brett") .getResultList; assertEquals(1, list.size);

}

@Test public void successfulSameInMemoryObjectsReturnedFromDifferntQueries { final int personKey = insertPerson;

final Person pByKey = em.find(Person.class, personKey);

final Person pByWhere = (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) public void unsuccessfulCaseWrongOnClass { // fails because we're naming a class, not a table // So instead of PERSON we must use Person em.createQuery("from PERSON").getSingleResult; }

@Test(expected = IllegalArgumentException.class) public void unsuccessfulWrongFieldNameUsedInWhereWithNamedPerson { 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'");    }

@Test public void successfulColumnNameNotCaseSensitive { 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 // conventions em.createQuery("from Person p where FirstName='Brett'").getResultList; }

@Test(expected = IllegalArgumentException.class) public void unsuccessfulSettingParamterWithWrongIndex { // Indexes are 1-based, not 0-based. em.createQuery("from Person p where FirstName='Brett'").setParameter(0,               "Brett"); }

@Test(expected = IllegalArgumentException.class) public void unsuccessfulSettingParameterWhereThereAreNone { // There's no parameter here, this simply fails em.createQuery("from Person p where FirstName='Brett'").setParameter(1,               "Brett"); }

@Test(expected = IllegalArgumentException.class) public void unsuccessfulDoNotQuoteStringParameters { 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. *     */    private int insertPerson { final Address a1 = new Address("A Rd.", "", "Dallas", "TX", "75001"); final Person p1 = new Person("Brett", 'L', "Schuchert", a1);

if (!em.getTransaction.isActive) { em.getTransaction.begin; }       em.persist(p1); return p1.getId; }

private void clearPersonTable { if (!em.getTransaction.isActive) { em.getTransaction.begin; }

em.createQuery("delete from Person").executeUpdate; } } code