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

Thursday, May 28, 2009

What's new in 0.5.0

We just released version 0.5.0.

This release focuses on just one new feature, support for JPA. Both the search and DAO portions of the framework are now fully compatible with both standard Hibernate and with JPA.

This made for the biggest structural changes we've had so far and some changes in the way the framework is installed and configured. For more details on this, look to the wiki (InstallationAndConfiguration and FrameworkArchitecture).

In order to work with various JPA providers, the framework uses a MetadataUtil interface that must be implemented for the desired provider. At this point, the only implemented provider is Hibernate Entity Manager, but perhaps we will see a few others contributed to the project over time.

Monday, May 18, 2009

Release 0.4.3

We recently released a new version of Hibernate Generic DAO. We added find-by-example functionality and a "distinct" option to the search. We also formally separated the search and DAO portions so that search can be used independently.


Distinct

The distinct option can be set on a search in order to filter out duplicate results. As with plain HQL or SQL, only use this option if your search requires it because it does affect performance.

"Distinct" can only be used on queries that return a single field. Here are some examples:


search(new Search().setDistinct(true)); //would work. Only the root entity is returned for each result.
search
(new Search().setDistinct(true).addField("firstName"); //would work. Only the single "firstName" value is returned for each result.
search
(new Search().setDistinct(true).addField("firstName").addField("lastName")); //would NOT work. Two fields are returned for each result.


Find By Example

The framework implements find-by-example by processing an example entity and producing a Filter object. The resulting Filter would be added to a search, and then the search would be processed. This method provides for maximum flexibility because the developer can alter the Filter in any way after it's been created (security checks, transformations, etc.) and can add it to the search in any way (using junction, disjuction, logical operators, etc.).

There are two methods for making a Filter form an example entity. These methods can be found on all the DAOs and on the SearchFacade.


public Filter getFilterFromExample(Object example);
public Filter getFilterFromExample(Object example, ExampleOptions options);


The first one uses the default options and the second lets the developer specify a set of options. These options include:


· Ignore case.

· Use exact string matching, starts with, ends with or contains.

· Exclude null-valued properties

· Exclude zero-valued properties

· Specify a list of properties to exclude


Here then is the simplest example of making a find by example method with no options:


public List findByExample(Person person) {

return dao.search(new Search().addFilter(dao.getFilterFromExample(person)));

}


A more complex example would be:


public List findSubordinatesByExample(Person manager, Person example) {

ExampleOptions options = new ExampleOptions();

options.setLikeMode(ExampleOptions.START);

options.setExcludeZeros(true);

Search search = new Search();

search.addFilterEqual("manager", manager);

search.addFilter(dao.getFilterFromExample(example, options));

return dao.search(search);

}


Using Search Alone

The search functionality of the framework can now be used without the DAOs. To make this possible we separated the framework code into two JARs and introduced a new SearchFacade interface.


The first JAR is trg-search.jar. This contains all the search functionality as well as the SearchFacade. The second is trg-dao.jar. You can use trg-search.jar by itself, but trg-dao.jar requires trg-search.jar. trg-dao.jarcontains the base DAO implementation as well as the “standard” and “original” generic and general DAOs.


The new SearchFacade interface has basically all the same search methods found on the DAOs, except without all the other DAO methods. Here is the interface (see also the javadoc: http://hibernate-generic-dao.googlecode.com/svn/tags/0.4.3/trg-search/doc/com/trg/search/SearchFacade.html).


public interface SearchFacade {

public List search(ISearch search);

public List search(Class searchClass, ISearch search);

public int count(ISearch search);

public int count(Class searchClass, ISearch search);

public SearchResult searchAndCount(ISearch search);

public SearchResult searchAndCount(Class searchClass, ISearch search);

public Object searchUnique(ISearch search);

public Object searchUnique(Class searchClass, ISearch search);

public Filter getFilterFromExample(Object example);

public Filter getFilterFromExample(Object example, ExampleOptions options);

}


HibernateSearchFacade implements the SearchFacade interface. It needs to be configured by setting the sessionFactory property, either as a constructor argument or through the setSessionFactory() method. It uses SessionFactory.getCurrentSession() to get a Session when performing queries. This behavior can be overridden by extending HibernateSearchFacade and overriding the getSession() method. See also the "Hibernate session strategy" section in the "Details and Tips" on the UserGuide.

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: