JPA+Tutorial+3+-+FAQ

JPA Tutorial 3 - FAQ
 * **Phone number length is set to 11 in the annotation in the exercise, but phone numbers are 12. What's happening?** //It will get truncated (in hypersonic)//
 * **TDD: Is there a tool (eclipse plugin) to generate a concrete class based on a test case?** //Use Quick-fix (Ctrl-1 or click the icon on the sidebar) to create the class, and stub methods.//
 * **When do Named Queries get compiled?** //When you create the EntityManager factory.//
 * **Is there something that can use to see the db structure based on the mappings?** //After the entitymanager creates the db, use something like DB Visualizer//

What did we learn/observe so far (mid-day)?

 * varargs for methods
 * cascading types - persist, all, refresh. propagates operations (merge/update/persist/refresh) across entities. Saves you from having to persist things.
 * jpa requires jdk 1.5
 * the @column annotation sets the name of the column in the database. also lets you specify things like width/length (attribute of the annotation).
 * debugging good
 * eclipse can gen hashcode/equals

What did we learn/observe so far (end of day)?

 * Brett: Why we use a DAO //Encapsulates data access, hides entity manager calls. Brett: Seperation of Concerns.//
 * Brett: Contrast the Library to the DAO's //Library is not an entity. Library is the 'go-between' (brett: facade design pattern).//
 * //Brett: Set em with a setter....why?// When you get your objects, they're fully configured (nice). Brett: makes it more testable
 * //Brett: What's @column for?// Defines attributes for a particular field in DB. Brett: affects physical characteristics as opposed to logical.
 * //Brett: What do you think about variables args?// saves lines of code
 * //Brett: what is suppresswarnings for?// brett: hide a warning based on actual query parameter type (not available at compile-time)
 * //Brett: named query and named queries?, why not put multiple named queries on the same object?// You can have only one version of the annotation on a given object
 * //Brett: opinions on base dao?// confusing, brett: heavy-handed/overkill
 * //Brett: EntityManagerBaseTest vs. BaseDAODBTest?// helps if you decide you want to change how you're accessing your database.
 * //Brett: opinions on refactoring as you go?// have to look at code to understand what's changing (head nods)
 * //Brett: overriding methods? (annotation)// gives compiler ability to flag problem. some class discussion of when needed, when not...
 * //Brett: @temporal// Brett:time/datastamp

//What else have you learned today?//
 * //Specifying the field for the join table//
 * //Comments in the code today were more helpful (than yesterday)//
 * //Cascading with a many-to-many relationship -- you can only put mappedBy on one side, but you can put cascade attributes on both sides. Cascading is for convenience -- less calls to entity manager.//
 * //In the book where define many-to-one (loan), there's an orderBy?// defines the sort order

//Day 3 - Tutorial #3 Questions//
 * //**Patron has a one-to-many for fines, but no many-to-one on the fines side. Why?**// Just an example of a uni-directional relationship.
 * //**Why is insertable false? (in exercise)**// We think: So that loan has to point at things which already exist. (as opposed to creating new loan/patron at same time)
 * //Seems like more stuff should be done in the library ?// Hold off on that because the next few exercises build up additional requirements which may change your mind

//What else have you learned today?//
 * //How we can create/persist a given entity//
 * //Named queries//
 * //Query syntax is better/easier//

//Notes for Brett://
 * //Need to break up tutorial a bit more.//

//Responses to questions in the exercises//
And the new feature that doesn't allow to checkout with overdue books.
 * A Patron can return a book while having an overdue book
 * Below are the tests to check everything:**

These tests are in LibraryTest.java code format="java5" @Test public void patronHasNumberOfOverdueBooks { final Patron p = createPatron; final Book b1 = createBook; final Book b2 = createBook; library.checkout(p.getId, CURRENT_DATE, b1.getId); int numOfBooks; numOfBooks = library.getNumberOfOverdueBooksOfPatron(p, CURRENT_PLUS_14); assertEquals(0, numOfBooks); library.checkout(p.getId, CURRENT_PLUS_8, b2.getId); numOfBooks = library.getNumberOfOverdueBooksOfPatron(p, CURRENT_PLUS_15); assertEquals(1, numOfBooks); library.returnBook(CURRENT_PLUS_8, b1.getId); numOfBooks = library.getNumberOfOverdueBooksOfPatron(p, CURRENT_PLUS_15); assertEquals(0, numOfBooks); }

// My change @Test public void patronCannotCheckoutWithOverdueBooks { final Patron p = createPatron; final Book b1 = createBook; library.checkout(p.getId, CURRENT_DATE, b1.getId);

final Book b2 = createBook; try { library.checkout(p.getId, CURRENT_PLUS_15, b2.getId); fail(String.format("1. Should have thrown exception: %s", PatronHasOverdueBooks.class .getName)); }       catch (PatronHasOverdueBooks e) { assertEquals(1, e.getNumberOfOverdueBooks); final Book b3 = createBook; library.checkout(p.getId, CURRENT_DATE, b2.getId); try { library.checkout(p.getId, CURRENT_PLUS_15, b3.getId); fail(String.format("2. Should have thrown exception: %s", PatronHasOverdueBooks.class.getName)); }           catch (PatronHasOverdueBooks e1) { assertEquals(2, e1.getNumberOfOverdueBooks); }           int numOfBooks = library.getNumberOfOverdueBooksOfPatron(p, CURRENT_PLUS_14); assertEquals(0, numOfBooks); }   }

code


 * And here are the changes in project:**

There is a new exception class called: **PatronHasOverdueBooks** Here it is: code format="java5" package exception;

/** * Thrown when a Patron attempts checkout while he has overdue books. */ public class PatronHasOverdueBooks extends RuntimeException { private static final long serialVersionUID = 7328551028997485470L; private final int numberOfOverdueBooks; public PatronHasOverdueBooks(final int numberOfOverdueBooks) { this.numberOfOverdueBooks = numberOfOverdueBooks; }   public int getNumberOfOverdueBooks { return this.numberOfOverdueBooks; }

}

code

In Library class, I added to the checkout method a validation for overdue books: code format="asp" public void checkout(final Long patronId, final Date checkoutDate, final Long... bookIds) { ...       // Checking number of overdue books of the Patron int booksOverdue = getNumberOfOverdueBooksOfPatron(p, checkoutDate); if (booksOverdue != 0) { throw new PatronHasOverdueBooks(booksOverdue); }

...   }

code

Also, in Library class, the new method: getNumberOfOverdueBooksOfPatron code format="java5" public int getNumberOfOverdueBooksOfPatron(final Patron patron, final Date compareDate) { return getLoanDao.numberOfOverdueBookOfPatron(patron, compareDate); }

code

code format="java5" /**    * Return number of overdue books of this patron *    * @param patron * @param compareDate * @return int - The number of overdue books */   public int numberOfOverdueBookOfPatron(final Patron patron, final Date compareDate) { final Query query = getEm.createNamedQuery("Loan.overdueBooksOfPatron"); query.setParameter("date", compareDate); query.setParameter("patron", patron);
 * LoanDao can return the number of overdue books of specific Patron:**

return query.getResultList.size;

}

code

It uses a new named-query. One of the parameter is the Patron (not the patron's id). I wanted to see how the join works ... code format="java5" @NamedQuery(name = "Loan.overdueBooksOfPatron", query = "SELECT l.book FROM Loan l WHERE l.dueDate < :date AND l.patron = :patron") code