I'm writing a Spring MVC 3.2.3 and Hibernate 4.2.1 application, just starting it's architecture. I decided to go with the Generic Dao pattern, since I'll be using a lot of common CRUD operations. I know that JPA has been around for a while, but I'd really love to achieve this using the generic dao pattern. To the issue it self. Everything went ok when setting up things and testing WITH ONE ENTITY. But as soon as I added a second one, I began to see errors:
"No qualifying bean of type [com.segurosweb.daos.GenericDao] is defined: expected single matching bean but found 2: cobradorDaoImpl,productorDaoImpl".
I understand that this is because Spring can not tell at startup time, which component to inject, but I dont know how to solve this.
The Generic DAO implementation that I used is:
GenericDao.java
package com.segurosweb.daos;
import java.util.List;
public interface GenericDao<T> {
public void saveOrUpdate(T dom);
public List<T> getAll();
public T get(long id);
}
GenericDaoImpl.java
package com.segurosweb.daos;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@SuppressWarnings("unchecked")
@Repository
public abstract class GenericDaoImpl<T> implements GenericDao<T>{
private Class<T> type;
@Autowired
private SessionFactory sessionFactory;
@SuppressWarnings("rawtypes")
public GenericDaoImpl(){
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
type = (Class) pt.getActualTypeArguments()[0];
}
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
... all other implementation...
}
CobradorDao.java
package com.segurosweb.daos;
import com.segurosweb.entities.Cobrador;
public interface CobradorDao extends GenericDao<Cobrador>{
}
CobradorDaoImpl.java
package com.segurosweb.daos;
import org.springframework.stereotype.Repository;
import com.segurosweb.entities.Cobrador;
@Repository
public class CobradorDaoImpl extends GenericDaoImpl<Cobrador> implements CobradorDao{
}
GenericService.java
package com.segurosweb.service;
import java.util.List;
public interface GenericService<T> {
public void saveOrUpdate(T dom);
public List<T> getAll();
public T get(long id);
}
GenericServiceImpl.java
package com.segurosweb.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.segurosweb.daos.GenericDao;
public class GenericServiceImpl<T> implements GenericService<T>{
@Autowired
private GenericDao<T> tDao;
@Override
public void saveOrUpdate(T dom) {
tDao.saveOrUpdate(dom);
}
@Override
public List<T> getAll() {
return tDao.getAll();
}
@Override
public T get(long id) {
return tDao.get(id);
}
}
CobradorService.java
package com.segurosweb.service;
import com.segurosweb.entities.Cobrador;
public interface CobradorService extends GenericService<Cobrador>{
}
CobradorServiceImpl.java
package com.segurosweb.service;
import org.springframework.stereotype.Service;
import com.segurosweb.entities.Cobrador;
@Service
public class CobradorServiceImpl extends GenericServiceImpl<Cobrador> implements CobradorService{
}
And my Controller, which has a very simple url mapping to test that everythin works (or doesn't!)
package com.segurosweb.controllers;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.segurosweb.entities.Cobrador;
import com.segurosweb.service.CobradorService;
@Controller
@RequestMapping("/cobradores/**")
public class CobradorController {
static final Logger log = LogManager.getLogger(CobradorController.class.getSimpleName());
@Autowired
private CobradorService cobServ;
@RequestMapping(value="view.html",method = RequestMethod.GET)
public ModelAndView setUpForm(ModelMap model){
log.info("cobradores/view.html hitted.");
cobServ.saveOrUpdate(new Cobrador("emi","lio","hola","321"));
return new ModelAndView("/secure/Productores");
}
}
Cobrador.java is a very simple POJO class annotated with @Entity.
And I also have matching interfaces and implementations for another entity, called Productor: ProductorDao, ProductorDaoImpl, ProductorService and ProductorServiceImpl.
The exact error Im getting is:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cobradorController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.segurosweb.service.CobradorService com.segurosweb.controllers.CobradorController.cobServ; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cobradorServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.segurosweb.daos.GenericDao com.segurosweb.service.GenericServiceImpl.tDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.segurosweb.daos.GenericDao] is defined: expected single matching bean but found 2: cobradorDaoImpl,productorDaoImpl
So, am I missing something important here? I'd like to stick to this Generic DAO pattern for now, unless you guys tell me that is veeeeeeeeeeeeeeeeeery bad idea.
Thanks in advance for any help you guys can give me!