Generische Dao, service-layer und mehrere passende Bohnen
Schreibe ich einen 3.2.3 Spring MVC und Hibernate 4.2.1 Anwendung, einfach zu starten ist-Architektur. Ich beschloss, gehen mit dem Generischen Dao-Muster, da werde ich mit einer Menge von gemeinsamen CRUD-Operationen. Ich weiß, dass JPA hat schon eine Weile herum, aber ich würde wirklich lieben, um dies zu erreichen verwenden die generische dao-Muster.
Auf die Frage selbst ein. Ging alles ok beim einrichten der Dinge und die Prüfung MIT EINER EINHEIT. Aber sobald ich fügte hinzu, eine zweite, ich begann zu sehen, Fehler:
"Kein gültiges bean des Typs [Kom.segurosweb.daos.GenericDao] definiert ist: erwartete einzigen passenden Bohnen gefunden, aber 2: cobradorDaoImpl,productorDaoImpl".
Ich verstehe, dass dies ist, weil der Frühling kann nicht sagen, beim Systemstart, welche Komponente zu injizieren, aber ich weiß nicht, wie man dieses Problem lösen.
Das Generische DAO-Implementierung, die ich benutzt habe ist:
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{
}
Und mein Controller hat einen sehr einfachen url-mapping zu testen, dass everythin funktioniert (oder nicht!)
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 ist ein sehr einfaches POJO-Klasse annotiert mit @Entity.
Und ich habe auch passende Schnittstellen und Implementierungen für eine andere Entität, genannt Productor: ProductorDao, ProductorDaoImpl, ProductorService und ProductorServiceImpl.
Den genauen Fehler Im immer ist:
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, ich bin fehlt etwas wichtiges? Ich möchte an diese Generische DAO-Muster für jetzt, es sei denn, Sie Jungs sagen mir, dass ist veeeeeeeeeeeeeeeeeery schlechte Idee.
Vielen Dank im Voraus für jede Hilfe, die Sie Jungs geben mir!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Für den Anfang würde ich drop das Generische DAO und wechseln Sie zu Spring Data JPA, versuchen Sie nicht, das Rad neu zu erfinden, und es spart Ihnen aus der Schrift eine andere Art von in-house-framework.
Bezug auf Generische Dienste, oder besser service-Methoden, die man-auf-einem Aufruf der entsprechenden Methoden auf die dao im Allgemeinen das ist, imho, ein design-Geruch. Der Dienst sollte bieten business cases/Anwendungsfälle zu lösen. Eine Methode wie
saveOrUpdate
ist nicht wirklich etwas, das hat wirtschaftliche Bedeutung. In diesen Fällen würde ich wohl auch den direkten Aufruf des repositories (hinzufügen einer anderen Ebene für die Auffüllung der Schicht ist nicht klug, imho).Es ist eine Frage/blog gibt, die grundsätzlich zum gleichen Ergebnis kommt (ich kann einfach nicht mehr finden, war ein Kommentar von Oliver Gierke, der Betreuer der Spring Data JPA.
Das problem ist, dass der Frühling-Versionen vor 4.0 haben Probleme mit dependency injection und generische Schnittstellen, dies wurde gelöst im Frühjahr 4.0
Links:
Im Frühjahr 3x version ist es ein problem zu identifizieren, die entsprechende bean selbst, die Sie verwendet haben generische Typ. Spring 4 gelöst wurde dieser bug. also nach mir musst du mit @Qualifier annotation für sagen, Frühling-container, die Bohne, die Sie wollen zu injizieren, die gleichen Eltern-Typ.
Ich hoffe, dass es helfen, voll für Sie.
Sollten Sie behoben werden, indem Sie diesen Code.
GenericServiceImpl.java
CobradorServiceImpl.java