This blog for Hibernate Generic DAO Project has been moved to WordPress http://hibernategenericdao.wordpress.com/. Bye bye Blogger!

Friday, March 20, 2009

Customizable Generic DAOs (The final word on New DAO Methods)

After much internal debate as to which methods to include in our generic DAOs so as to be simple but also flexible enough for a wide variety of development scenarios, we came up with a different sort of solution. We decided simply to make it easy for developers to use their own DAO interfaces and select what methods they would like for their own project.

The change was introduced in version release 0.3.4. We moved all the heavy code to a DAO base class, BaseDAOImpl, that implements a large number of possible methods with that we thought developers might want. These methods all have protected visibility. Developers can now either use our default thin DAO implementation on top of this or make their own by simply selecting which methods they want to expose and wrapping them with public methods according to their own naming convention. In fact to prove how easy this is, the framework currently includes two separate sets of DAOs, "original" with the same methods from our original DAO and "standard" which has a new and improved (at least we think so) set of methods.

Want to know how to make your own DAOs for the Hibernate Generic DAO Framework?
All you have to do is create a class that extends BaseDAOImpl. Actually you'll need one class for the GenericDAO and one for the GeneralDAO if you want to use both, and you will probably also want to create interfaces for these classes as a standard practice. The easiest way is to follow our examples. Just look at the GenericDAOImpl and GeneralDAOImpl classes in these packages:

com.trg.dao.dao.standard (our standard DAOs)
com.trg.dao.dao.original (our original DAOs)

and also the base class javadoc.

The final word on New DAO Methods
In the mean time, we did have to decide what methods to include in our standard DAO. Since I have already written a couple posts about this, I figure I should also post the final decision. So without further ado...

(See javadocs: GeneralDAO, GenericDAO)

Interface for GeneralDAO:

public interface GeneralDAO {

      public T find(Class type, Serializable id);

      public T[] find(Class type, Serializable... ids);

      public T getReference(Class type, Serializable id);

      public T[] getReferences(Class type, Serializable... ids);

      public boolean save(Object entity);

      public boolean[] save(Object... entities);

      public boolean remove(Object entity);

      public void remove(Object... entities);

      public boolean removeById(Class type, Serializable id);

      public void removeByIds(Class type, Serializable... ids);

      public List findAll(Class type);

      public List search(ISearch search);

      public Object searchUnique(ISearch search);

      public int count(ISearch search);

      public SearchResult searchAndCount(ISearch search);

      public boolean isAttached(Object entity);

      public void refresh(Object... entities);

      public void flush();

}


Interface for GenericDAO:

public interface GenericDAOextends Serializable> {

      public T find(ID id);

      public T[] find(ID... ids);

      public T getReference(ID id);

      public T[] getReferences(ID... ids);

      public boolean save(T entity);

      public boolean[] save(T... entities);

      public boolean remove(T entity);

      public void remove(T... entities);

      public boolean removeById(ID id);

      public void removeByIds(ID... ids);

      public List findAll();

      public List search(ISearch search);

      public T searchUnique(ISearch search);

      public int count(ISearch search);

      public SearchResult searchAndCount(ISearch search);

      public List searchGeneric(ISearch search);

      public Object searchUniqueGeneric(ISearch search);

      public boolean isAttached(T entity);

      public void refresh(T... entities);

      public void flush();

}

Thursday, March 19, 2009

Release 0.4.2

We just release a new build 0.4.2. It adds some handy new features to the search and tightens down null handling on the search.

The main new feature of 0.4.2 is the collection operators for search filters. These include SOME, ALL, NONE, EMPTY and NOT_EMPTY operators. These are fairly self-explanatory:

  SOME matches collections where the specified condition is true for at least one element.
  ALL matches collections where the specified condition is true for every element.
  NONE matches collections where the specified condition is not true for any elements.

  EMPTY matches collections that have no elements.
  NOT_EMPTY matches collections that have at least one element.

Additionally, EMPTY matches null values of non-collection types and empty strings in string types. Of course NOT_EMPTY does the inverse.

NULL and NOT_NULL operators were added to replace using the EQUAL operator with a null value. EQUAL operators with null values are now ignored.

Now if any filter with an operator that expects a value has a null value, that filter is ignored.

Finally, we ensured proper support for HQL special properties ".id", ".class" and ".size". Anywhere these can be used in HQL they can also be used in a search.

For further explanation and examples of all this functionality, see the section on filtering in http://code.google.com/p/hibernate-generic-dao/wiki/Search.


Another addition are the search walkers in SearchUtil. These are utilities for walking the lists of filters, fields, sorts and fetches in a search. Without these tools it can be especially tricky to visit every filter in a list because filters can have sub-filters, but these walkers provide the additional advantage of preserving the original list and only duplicating it if changes are made.

One purpose of these walkers might be to check for references to certain properties and alter or remove them. We use them internally to clean up null values and do validity and security checks on searches before we process them.

See the javadoc:

And an example: