views:

46

answers:

3

I have DAO's for each table, that all implement an interface.

Now I want to be able to (potentially) swap database layer implementations.

So my strategy is to create a DaoFactory, and this DaoFactory will be specific to a particular implemenation of my DAO's.

So I will have DAO's for hibernate. Then a DaoHibernateFactory that will look like:

public class DaoHibernateFactory implements DaoFactory
{


     public UserDao GetUserDao() {

          return new UserHibernateDao();
     }


}

Then in all my manager/service classes, I will use whichever Dao___Factory is currently wired via spring ioc.

Does this make sense? Suggestions?

+4  A: 

I would have separate configuration files for each implementation, rather than using factories. That way spring can inject your DAOs for you, and you don't have to call or maintain an extra factory class.

For example:

hibernate-data.xml:

<bean id="userDAO" class="com.foo.dao.hibernate.HibernateUserDao">
    ...
</bean>

ibatis-data.xml:

<bean id="userDAO" class="com.foo.dao.ibatis.IBatisUserDao">
    ...
</bean>

etc.

Then you can swap out the implementation by changing which -data file is included in your web.xml.

Jason Day
+1 - this is the simple solution.
Stephen C
+1  A: 

I would say you're missing the point badly if you think you need to write a factory. The Spring application context is the factory in this case: a declarative, dynamic object factory. The classes that use your factory lose the advantage of Spring.

You could write a generic DAO so you don't have to maintain all that code.

package hibernate.policy.persistence;

import java.io.Serializable;
import java.util.List;

public interface GenericDao<T, K extends Serializable>
{
    T find(K id);
    List<T> find();
    List<T> find(T example);
    List<T> find(String queryName, String [] paramNames, Object [] bindValues);

    K save(T instance);
    void update(T instance);
    void delete(T instance);
}
duffymo
+2  A: 

Since you are using dependency injection, you should try to use the wiring that is provided out of the box from the DI framework in question rather than writing your own factories.

The current problem can be solved using SpringPropertyPlaceHolder and a simple convention around the naming of the DAOs in the spring configuration file.

Steps: 1. First use some naming convention to name the Ids of your individual DAOs and configure them in the spring file. Ex:

<bean id='hibernateUserDao' class='UserHibernateDao'/>
<bean id='ibatisUserDao' class='UserIbatisDao'/>

Here we are saying that all Hibernate Daos begin with hibernate and all ibatis Daos begin with ibatis etc.

2.Next configure the consumer of the Daos. Make sure that the wiring is dynamic depending on properties.

<bean id='daoconsumer' class='some.consumer.class'>
  <property name='dao' ref='${daoImpl}UserDao'/>
</bean>

3.After that configure Spring Property place holder in your spring file.

<bean id="propertyConfigurator" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>classpath:/path/to/app.properties</value>
    </property>
</bean>

4.Finally you write the app.properties with the single line.

daoImpl=hibernate # choose hibernate implementations.

Now, the daoImpl would get replaced by "hibernate". The other advantage of this technique is that SpringPropertyPlaceHolder can also obtain properties from the environment which it can use in preference to the app.properties (depends on a configuration parameter look up the javadocs for details)

Hence you can configure your app behavior using environment properties as well which can be pretty powerful.

Alternative 2:

You can also use Maven Profiles to achieve similar behavior. Maven has the ability to "filter" your resources - in this case it would replace placeholders with some strings depending on the maven profile that it is executing under. You can leverage this feature to generate app packages (jars, ears etc.) that work with a given implementation (like hibernate,ibatis etc). Obviously, this is less flexible than the PropertyPlaceHolder approach but can be preferable under certain conditions.

raja kolluru
@raja kolluru Nice solution (+1)
Arthur Ronald F D Garcia
+1 nice to know, but more complicated than I want.
Blankman
thanks @Arthur.@Blankman, it is not too complex if you consider the fact that most spring configurations anyway use the property place holder configurer with some properties file anyways. It is a one time set up.
raja kolluru