Search code examples
javaspringhibernatespring-mvcannotations

How to declare a DAO variable using an interface but put in it a concrete implementation in Spring Framework?


I am studying how to integrate Spring Framework with Hibernate and I have some doubt about it.

I have develop a personal example that work well but I am not sure about the architecture of this project.

So I have an interface named PersonDAO in which I have declared the CRUD operation that I would in my DAO

Then I have created a concrete implementation of this interface by the class PersonDAOImpl that implement the previous interface.

Then I have create the following main class to test my dao object:

package org.andrea.myexample.HibernateOnSpring;

    import org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl;
    import org.andrea.myexample.HibernateOnSpring.entity.Person;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class App {
   
    public static void main( String[] args ){
        
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        System.out.println("Contesto recuperato: " + context);
        
        Person persona1 = new Person();
        
        persona1.setFirstname("Pippo");
        persona1.setLastname("Blabla");
        persona1.setPid(1);
        
        System.out.println("Creato persona1: " + persona1);
        
        PersonDAOImpl dao = (PersonDAOImpl) context.getBean("personDAOImpl");
        
        System.out.println("Creato dao object: " + dao);
        
        dao.addPerson(persona1);
        
        System.out.println("persona1 salvata nel database");
        
    }
}

The DAO work well and my object is correctly persisted on my database but I have the following architectural doubt: Why have I an interface if I am not using it?

Finally, in this way, I could not have the interface and use directly the concrete class...

I think that, architecturally, this is so bad...

I have try to change my App.java class and try to use the DAO object in this way:

PersonDAO dao = (PersonDAO) context.getBean("personDAOImpl");

but don't work...

In this tutorial: http://viralpatel.net/blogs/spring3-mvc-hibernate-maven-tutorial-eclipse-example/

there is an other situation, that really use the interface, in which there is a ContactServiceImpl class in which I have the ContactDAO variable declared using the @Autowired annotation:

@Autowired
private ContactDAO contactDAO;

ContactDAO is a DAO interface but Spring autowire an object that is an istance of it's implemtantio ContactDAOImpl (that is annotated using @Repository)

So, using the **@Autowired annotation, in this code I can declare a variable using an interface but put in this variable the reference to a concrete implementation of it!

In my project I don't use the annotation bean configuration mechanism but I am using the XML configuration mechanism...but I think that also in this case I can do something like it...

I my project XML configuration file I have declared my bean like this:

<bean id="personDAOImpl" class="org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl" >
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

What can I do to declare my dao variable as an interface and put in it a concrete implementation of it? (still using XML configuration)

This is the stack trace error that I have when I use:

    PersonDAO dao = (PersonDAO) context.getBean("personDAOImpl");

in my App.Java test class

INFO: Using DataSource [org.apache.commons.dbcp.BasicDataSource@7363c839] of Hibernate SessionFactory for HibernateTransactionManager Contesto recuperato: org.springframework.context.support.ClassPathXmlApplicationContext@591f5ff9: startup date [Sat Feb 23 11:42:25 CET 2013]; root of context hierarchyException in thread "main" Creato persona1: org.andrea.myexample.HibernateOnSpring.entity.Person@23653628 java.lang.ClassCastException: org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl$$EnhancerByCGLIB$$d46b3a86 cannot be cast to org.andrea.myexample.HibernateOnSpring.dao.PersonDAO at org.andrea.myexample.HibernateOnSpring.App.main(App.java:27)

Thanks


Solution

  • The very essence of interface and concrete implementation is to preserve polymorphism. In a testing environment you could use a different concrete implementation but same interface, while in developing mode another implementation could be put in the xml configuration. It would be easily for you to swap xml configurations without changing the java code like swapping from developing to testing environment or another tester would use your same code but with different xml configurations.

    if you are going to use directly the implementation in the xml, then you will lose the power of polymorphism, and would need to change the java code if you have to swap to a different implementation.

    Your PersonDAOImpl must implement PersonDAO, such as

    public class PersonDAOImpl implements PersonDAO
    

    Xml configuration is only use for dependency injection or singleton bean instances across the application, it doesn't have anything to do with preserving polymorphism. What you have to do is to follow the interface-implementation of java.