Java Generic DAO

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

Monday, February 28, 2011

Version 1.0.0 released to Maven Central; new package names

Version 1.0.0 of Hibernate Generic DAO (http://code.google.com/p/hibernate-generic-dao/) was released today. It has a few small bug fixes, but the big changes are the new build and deployment strategy and the new package names.

Read more at the new Hibernate Generic DAO blog (http://hibernategenericdao.wordpress.com/2011/02/27/version-1-0-0-released).

Moving to WordPress

From now on, the official Hibernate Generic DAO blog is moving to WordPress. Here's the link: http://hibernategenericdao.wordpress.com.

I just got fed up with trying to copy and paste code into Blogger. It always seems to do horrific things with formatting and also has no idea what to do if you include < and > symbols. I'm tired of spending more time fighting with formatting and escaping my blog post than actually writing the content.

So bye bye Blogger, one of the few Google products I don't love.

Saturday, June 12, 2010

Configuring Hibernate Generic DAO with JPA

Version 0.5.0 introduced JPA to the "Hibernate" Generic DAO. Version 0.5.1 added a a JPAAnnotationMetadataUtil instance that makes simple non-Hibernate JPA configuration a bit simpler. Future versions willhopefully provide full out-of-the-box support for all JPA 2.0 providers. Until then, this post will explain how to configure Hibernate Generic DAO with JPA 1.0. (Although I hear some people have gotten it to work with 2.0 http://groups.google.com/group/java-generic-dao/browse_thread/thread/a3e792d989b55bb3)


There is an example configuration using Spring and Hibernate JPA in our SVN repo. You can download or browse the source online here: http://code.google.com/p/hibernate-generic-dao/source/browse/#svn/tags/0.5.1/sample/jpa-hibernate-maven%3Fstate%3Dclosed.


Let's get started with a diagram...


In the above diagram each box represents a singleton instance of a class (except EntityManager). These are all you need to know to set up the framework in your project. Let's take a look at the parts:


JPASearchProcessor: You will need one singleton instance of the JPASearchProcessor class for each persistence unit in your project. (Most projects have only one persistence unit and thus only one JPASearchProcessor.) The JPASearchProcessor has only one dependency, it must have an instance of MetadataUtil passed into its constructor.


MetadataUtil: Again you will need one singleton instance of MetadataUtil per persistence unit. The MetadataUtil is used to inform the framework of the structure and relationships in your data model.


While there is only one implementation of JPASearchProcessor, Hibernate Generic DAO ships with two build-in implementations of MetadataUtil. The first implementation that comes with the framework is HibernateMetadataUtil. HibernateMetadataUtil can only be used with Hibernate's JPA implementation. The second is JPAAnnotationMetadataUtil. This is a beta implementation that looks at the JPA annotations on Java classes to determine the data model. It should theoretically work with any JPA 1.0 implementation, but it has only been tested on some basic data models. If neither of these is sufficient for your needs, you can code your own implementation of the MetadataUtil interface. [In fact if someone wants to implement one using JPA 2.0's metadata model, that would be a major contribution to the project, allowing us to fully support any JPA 2.0 implementation out of the box.]


In our sample project in SVN we use Spring framework to create these two singletons and wire them together. In this case we are using the HibernateMetadataUtil class. This requires a reference to the Hibernate EntityManagerFactory which should be configured elsewhere with your Hibernate JPA configuration. Here is a snippet from the applicationContext.xml that show these two singletons.


<bean id="searchProcessor" class="com.trg.search.jpa.JPASearchProcessor">

<constructor-arg ref="metadataUtil" />

</bean>


<bean id="metadataUtil" class="com.trg.search.jpa.hibernate.HibernateMetadataUtil"

factory-method="getInstanceForEntityManagerFactory">

<constructor-arg ref="entityManagerFactory" />

</bean>


An alternative configuration that uses JPAAnnotationMetadataUtil would be as follows. JPAAnnotationMetadataUtil does not require any configuration options. It just looks for annotated classes on the classpath.


<bean id="searchProcessor" class="com.trg.search.jpa.JPASearchProcessor">

<constructor-arg ref="metadataUtil" />

</bean>


<bean id="metadataUtil" class="com.trg.search.jpa.JPAAnnotationMetadataUtil"/>



Diagram showing the dependencies for the two different MetadataUtil implementations. HibernateMetadataUtil requires a reference to the HibernateEntityManager. JPAAnnotationMetadataUtil stands alone.


Now that we have that set up, we turn to our individual DAOs. Each one requires two things, (1) a reference to the JPASearchProcessor singleton and (2) an EntityManager (not a singleton). You can decide how the DAO will get an EntityManager when it needs it by overriding the getEntityManager() method of GenericDAOImpl or GeneralDAOImpl. In the case of our example, we rely on Spring framework to inject the current EntityManager into our DAOs via the @PersistenceContext annotation on the setEntityManager() method. We are also having spring automatically set our JPASearchProcessor via an @Autowired annotation. In order to make both of these apply to all our DAOs, we have a base class that all of them extend. This is not necessary, but in this case it’s convenient. Here’s the code for the BaseDAO class:


@Repository

public class BaseDAO<T, ID extends Serializable> extends GenericDAOImpl<T, ID> {

@Override

@PersistenceContext

public void setEntityManager(EntityManager entityManager) {

super.setEntityManager(entityManager);

}

@Override

@Autowired

public void setSearchProcessor(JPASearchProcessor searchProcessor) {

super.setSearchProcessor(searchProcessor);

}

}


We took a similar strategy for the GeneralDAO (See DecoratedGeneralDAOImpl in the sample code).


So that’s basically all there is to know about configuring the framework for use with JPA. For other installation information start at this wiki page (http://code.google.com/p/hibernate-generic-dao/wiki/InstallationAndConfiguration).


Best of luck. Our forum is found at http://groups.google.com/group/java-generic-dao. And if anyone wants to contribute to features of this open source project or the JPA 2.0 updates, let me know.

Thursday, March 11, 2010

Version 0.5.1 Released with a number of bug fixes

Tonight I pushed a new build (0.5.1) to the Maven repository. This has been a long time in coming, and consists primarily of bug fixes. (For a list of all issues fixed in this release see the Road Map).

There is one important change in the Generic DAO interface, however. We changed the signature of the search() and searchUnique() methods.

Old Signature:

List<ENTITY_CLASS> search(Search search);
ENTITY_CLASS searchUnique(Search search);

New Signature:

<EXPECTED_TYPE> List<EXPECTED_TYPE> search(Search search);
<EXPECTED_TYPE> EXPECTED_TYPE searchUnique(Search search);

The old signature assumed that every search would return the root entity type, but with the Fields and result mode options on the Search, this is not always so. The old solution for this was to have two additional methods: searchGeneric and searchUniqueGeneric which returned List<?> and Object types respectively. The new approach eliminates the need for these confusing methods.

If you are unfamiliar with this sort of generic method signature, what it does is determine the return type of the method based on the context from which it is called, effectively reducing the need for explicit casting. (Here's a more in-depth description.)

For example, if we're using the RESULT_ARRAY result mode...

Old way:

List<Object[]> results = (List<Object[]>) dao.searchGeneric(search);

New way:

List<Object[]> results = dao.search(search);

With the new method signatures, the Java compiler is able to infer from the type of the "results" variable that search() will return a list of type List<Object[]>. There is no longer a need to explicitly cast it in most cases.

In addition to all this, we added a new (Beta) implementation of MetadataUtil that uses JPA Annotations to determine the persistence meta model. The implication of this is that the framework should be able to be used, out of the box, with other JPA providers like OpenJPA, TopLink, etc. I hope to post more on just how to configure this when I have time.

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.