Rainy Day Inn A developer's journey through life

13Feb/120

Simplifying Generic Dao with factory pattern and Spring

The Generic Dao pattern has been the standard for building CRUD web application in Java.  One of the issue through is that you would have to know which Dao you need to use for which class.  Combining the factory pattern with generic Dao allows you to look up the appropriate Dao for each persisted type.

With the Generic Dao interface:

public interface GenericDao<T extends DataObject, ID extends Serializable> {
      T save (T object);
      T load (ID id);
      void remove (ID id);
      Class<T> getPersistedType();
}

With each data type in your application, you extend the interface to add more specific function, and override the generic CRUD functionality:

public interface UserDao extends GenericDao<User, String> {
     User findUserByEmail (String email);
}

Soon enough, you end up with lots of daos floating around.  In order to preform operation on an object you want to persist, you must also know which dao to use.  This is where the Factory pattern comes in handy:

public interface DaoFactory {
      <I extends GenericDao<T>, T extends DataObject> I getDao (Class<T> type, Class<I> implementation);
      <T extends BasicDocument> GenericDao<T> getDao (Class<T> type);
      Set<Class> getPersistentClasses ();
}

Then finally with Spring, you can wire it up using factory-method:

      <bean id="daoFactory" class="com.rainydayinn.DaoFactoryMongoImpl">
            <constructor-arg index="0" name="template" ref="mongoTemplate" />
      </bean>
      //Guest has special implementation in GuestDaoImpl
      <bean id="guestDao" factory-bean="daoFactory" factory-method="getDao">
            <constructor-arg index="0" type="java.lang.Class" value="com.rainydayinn.Guest" />
            <constructor-arg index="1" type="java.lang.Class" value="com.rainydayinn.GuestDaoImpl" />
      </bean>
      //Room just needs generic handling
      <bean id="roomDao" factory-bean="daoFactory" factory-method="getDao">
            <constructor-arg index="0" type="java.lang.Class" value="com.rainydayinn.Room" />
      </bean>

With the above, you can save any child class of DataObject without having to worry about which Dao to choose.  Note that since the dao factory methods are not static, do not include class property for the guestDao and roomDao beans.

daoFactory.getDao(myObject.getClass).save(myObject);

If Room class requires a different implementation, simply use the other constructor and pass the implementation to DaoFactory.

Be Sociable, Share!
    Comments (0) Trackbacks (0)

    No comments yet.


    Leave a comment

    Trackbacks are disabled.