The java.util.Map DAO
The more I code, the fewer dependencies I am willing to create.
For example, I used to have a common super interface that all persistent objects must inherit from in order to have an id-field. I used to have a common DAO interface that all DAOs implemented. But these add hard dependencies in my code.
Hiding the super interface for all entities was easy. Doing away with the DAO is harder. But I can use Maps to get rid of almost all custom code. There are two exceptions so far: Querying and some DAO utility operations like flushing.
The following is a proof-of-concept test. The code necessary to make it pass is not yet available, but I am envisioning the Map being replaced by a lazy but smart HibernateObjectMap without changing the code. Any feedback on this code would be welcome.
public class CategoryDAOTest extends TestCase {
protected Map categories = new HashMap();
public void testSavedEqualsRetrieved() {
Category savedCategory = new Category("category", 1223);
Category parentCategory = new Category("parent");
savedCategory.setParent(parentCategory);
savedCategory.addSubcategory("sub 1");
savedCategory.addSubcategory("sub 2");
// ???
categories.put(savedCategory, savedCategory);
Category retrievedCategory = categories.get(savedCategory.getId());
assertEquals("equality", savedCategory, retrievedCategory);
assertEquals("name", savedCategory.getName(), retrievedCategory.getName());
assertEquals("year", savedCategory.getCreationYear(), retrievedCategory.getCreationYear());
assertEquals("parent", savedCategory.getParent(), retrievedCategory.getParent());
assertEquals("subcategories", savedCategory.getSubcategories(), retrievedCategory.getSubcategories());
}
public void testFindByName() {
Category fooCategory = new Category("foo");
Category barCategory = new Category("bar");
Category bazCategory = new Category("baz");
categories.put(fooCategory, fooCategory);
categories.put(barCategory, barCategory);
categories.put(bazCategory, bazCategory);
Category retrievedCategory = Specifications.findSingle(categories, new Restrictions() {
public Filter populateFilter(Filter filter) {
return filter.where("name").eq("foo");
}
});
assertEquals(retrievedCategory, category);
}
public void testFindAll() {
Category fooCategory = new Category("foo");
Category barCategory = new Category("bar");
Category bazCategory = new Category("baz");
categories.put(fooCategory, fooCategory);
categories.put(barCategory, barCategory);
categories.put(bazCategory, bazCategory);
Collection matchedCategories = Specifications.find(categories, new Restrictions() {
public Filter populateFilter(Filter filter) {
return filter.matchAll();
}
});
assertSetEquals(asList(fooCategory, barCategory, bazCategory), matchedCategories);
}
public void testUnsavedChanges() {
Category category = new Category("foo");
categories.put(category, category);
DaoUtils.flushAndEvict(categories);
category = categories.get(category);
categoryDAO.flushAndEvictAll(categories);
category.setName("bar");
assertEquals("foo", categories.get(category).getName());
}
public void testSavedChanges() {
Category category = new Category("foo");
categories.put(category, category);
category = categories.get(category);
category.setName("bar");
categories.put(category, category);
assertEquals("bar", categories.get(category).getName());
}
public void testEquality() {
Category category = new Category("foo");
categories.put(category, category);
DaoUtils.flushAndEvict(categories);
Category retrievedCategory = categories.get(category);
assertNotSame(retrievedCategory, category);
assertEquals(category, retrievedCategory);
Category unsaved = new Category("foo");
assertFalse("unsaved should never equal saved", category.equals(unsaved));
}
public void testHashCodeIsUnchanged() {
Category category = new Category("foo");
long oldHashCode = category.hashCode();
categories.put(category, category);
Category retrievedCategory = categoryDAO.get(category);
assertEquals("before and after", oldHashCode, category.hashCode());
assertEquals("saved and retrieved", category.hashCode(), retrievedCategory.hashCode());
}
private List asList(Category... category) {
return Arrays.asList(category);
}
@SuppressWarnings("unchecked")
private void assertSetEquals(Collection expectedAsCollection, Collection actualAsCollection) {
Set expected = (expectedAsCollection instanceof Set) ? (Set)expectedAsCollection : new HashSet(expectedAsCollection);
Set actual = (actualAsCollection instanceof Set) ? (Set)actualAsCollection : new HashSet(actualAsCollection);
assertEquals(expected, actual);
}
}