Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 3 DI using generic DAO interface

I'm trying to use @Autowired annotation with my generic Dao interface like this:

public interface DaoContainer<E extends DomainObject> {
    public int numberOfItems();
    // Other methods omitted for brevity 
}

I use this interface in my Controller in following fashion:

@Configurable
public class HelloWorld {
    @Autowired
    private DaoContainer<Notification> notificationContainer;

    @Autowired
    private DaoContainer<User> userContainer;

    // Implementation omitted for brevity
}

I've configured my application context with following configuration

<context:spring-configured />
<context:component-scan base-package="com.organization.sample">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
   type="annotation" />
</context:component-scan>
<tx:annotation-driven />

This works only partially, since Spring creates and injects only one instance of my DaoContainer, namely DaoContainer. In other words, if I ask userContainer.numberOfItems(); I get the number of notificationContainer.numberOfItems()

I've tried to use strongly typed interfaces to mark the correct implementation like this:

public interface NotificationContainer extends DaoContainer<Notification> { }
public interface UserContainer extends DaoContainer<User> { }

And then used these interfaces like this:

@Configurable
public class HelloWorld {
    @Autowired
    private NotificationContainer notificationContainer;
    @Autowired
    private UserContainer userContainer;
    // Implementation omitted...
}

Sadly this fails to BeanCreationException:

org.springframework.beans.factory.BeanCreationException: Could not autowire field:   private com.organization.sample.dao.NotificationContainer com.organization.sample.HelloWorld.notificationContainer; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.organization.sample.NotificationContainer] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Now, I'm a little confused how should I proceed or is using multiple Dao's even possible. Any help would be greatly appreciated :)

like image 987
Peders Avatar asked May 17 '10 06:05

Peders


People also ask

What is generic DAO?

GenericDAO is a method to reduce boilerplate sources codes. EmployeesResource class. CRUD operations on WEB API. #create , #read , #update or #delete.

What is DAO interface in spring boot?

DAO stands for data access object. Usually, the DAO class is responsible for two concepts: encapsulating the details of the persistence layer and providing a CRUD interface for a single entity.

How does DAO work in spring?

It's a design pattern in which a data access object (DAO) is an object that provides an abstract interface to some type of database or other persistence mechanisms. By mapping application calls to the persistence layer, DAOs provide some specific data operations without exposing details of the database.

Is JPARepository a DAO?

It is about the DAO. In spring boot, there is JPARepository interface. This interface has been declare the methods such as save(), findById() . and we can use the JPARepository as follows.


1 Answers

Ok, I think I've found a fairly reasonable solution for this puzzle. One way of dealing with this would be creating interface and implementations for each and every entity in my domain model (as Espen pointed out in his answer earlier). Now, consider having hundreds of entities and respectively hundreds of implementations. That wouldn't feel right, would it?

I've discarded strongly typed sub-interfaces and I'm using generic interface instead:

@Service // Using @Service annotation instead @Configurable as Espen pointed out
public class HelloWorld {
    @Autowired
    private DaoContainer<Notification> notificationContainer;

    @Autowired
    private DaoContainer<User> userContainer;

    // Implementation omitted
}

Implementation for my DaoContainer interface would look something like this:

@Repository
public class DaoContainerImpl<E extends DomainObject> implements DaoContainer<E> {

    // This is something I need in my application logic
    protected Class<E> type;

    public int getNumberOfItems() {
       // implementation omitted
    }
    // getters and setters for fields omitted

}

And finally application context:

<context:spring-configured />
<context:component-scan base-package="com.organization.sample">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
    type="annotation" />
</context:component-scan>

<bean class="com.organization.sample.dao.DaoContainerImpl" id="userContainer">
    <property name="type" value="com.organization.sample.domain.DiaryUser" />
</bean>
<bean class="com.organization.sample.dao.DaoContainerImpl" id="notificationContainer">
    <property name="type" value="com.organization.sample.domain.DiaryNotification" />
</bean>

So basically I couldn't get pure generic autowiring to work, but this solution works for me (at least for now) :)

like image 103
Peders Avatar answered Sep 23 '22 01:09

Peders