2013-05-14 26 views
13

Ich habe einige Tutorials gelesen, und ich konnte sehen, dass die meisten der MVC-ImplementierungenHibernate und Spring - Dao, Dienste

basieren auf:

1) eine dao-Schnittstelle zum Beispiel "IUserDao"

2) eine dao impl dieser Schnittstelle - "mySimpleUserDaoImpl"

3) eine Service-Schnittstelle für persistance: "IUserService"

4) und einer Umsetz - „U serServiceImpl "

ist dies die beste Praxis? Ich meine, der Grund, warum ich diese Frage stelle, ist, dass es redundant erscheint, 30 Dienste mit getXById(), deleteX (x), createX (x) -Methoden zu haben, die mehr oder weniger dasselbe tun.

beachten Sie bitte, dass ich Frühjahr bin mit 3 und 4 überwintern, und ich habe ich beschlossen, diese Frage zu stellen, bevor ich meine Tastatur

Dank mit Code beginnen Zuschlagen.

+2

Sie können das Präfix "I" für Schnittstellen löschen. Der Benutzer sollte nicht wissen, dass er eine Schnittstelle erhält. Nennen Sie sie einfach 'UserDAO' und' UserService'. – Bart

+0

Vereinbar, fallen die I auf Schnittstellen. Ich persönlich nenne meine Dao-Klassen-Repositories nur, um sie in Einklang mit den Spring-Anmerkungen zu halten, aber das spielt keine Rolle. – bh5k

+1

Tutorials für eine Technologie sind in der Regel nicht mit Business-Logik, so dass sie keine guten Referenzen dafür sind. Es gibt eine ähnliche Frage, die für Sie hilfreich sein kann: http://StackOverflow.com/Q/3688664/217324 –

Antwort

9

Wenn Sie gerade mit der Entwicklung beginnen, schauen Sie in Spring JPA. Ein Dienst sollte One-to-Many-Repositorys (DAO) sein. Aber ich würde auch nicht mehr alles von Hand schreiben. Spring JPA eliminiert die grundlegenden CRUD- und Suchfunktionen sowie die Paginierung.

Here is a video, die durch die gesamte Konfiguration für Spring, JPA, Hibernate geht, und endet mit Spring Data JPA zeigt Ihnen alle der Boileplate-Code, der eliminiert wird.

Um Spring Data JPA, Repository-Schnittstelle endet als verwenden:

package com.mysampleapp.repository; 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.stereotype.Repository; 
import com.wcfgroup.model.Employee; 

@Repository("employeeRepository") 
public interface EmployeeRepository extends JpaRepository<Employee, Long> { 
    Employee findBySsn(String ssn); 
} 

Und dann die XML-Konfigurations Spring Data JPA zu verwenden: Jetzt wird

<jpa:repositories base-package="com.mysampleapp.repository"/> 

alle der Standardcode behandelt für dich. Sie müssen keine Basis-Repository-Klasse mehr mit Suchmethoden und grundlegenden CRUD-Funktionen erstellen. Die JpaRepository Schnittstelle bietet viele nette Funktionen und Sie müssen nichts für die Implementierung tun.

+1

Eine andere Sache, die über die Service-Schicht zu beachten ist, ist, dass Ihre @Transaction starten sollte.Wenn Sie also eine Transaktion über mehrere Repositorys zurücksetzen möchten, ist die Serviceebene genau dort, wo Sie sie ausführen. Aus diesem Grund sollte der Service Eins zu viele mit Repositories sein. – bh5k

1

Nein, es ist nicht notwendig, 30 Service-Schichten oder 30 Dao-Schichten zu haben. Sie sollten die Schichten nicht berücksichtigen, die Entität weise, aber die Business-Funktionalität weise.Es kann 5 oder 6 Entitäten für bestimmte Funktionen relevant sein und diese sollten in einer Schicht.Aber noch müssen Sie getXById(), deleteX (x), createX (x) in diesen redundanten Schichten haben, wenn sie benötigt werden.

4

Es ist notwendig, dao, daoImpl, service, serviceImpl für jedes Modell.

  • UserDao
  • UserDaoImpl
  • Userservice
  • UserServiceImpl

Sie eine generische Klasse EntityDaoImpl anf der inteface EntityDao wie folgt verwenden können:

EntityDao:

public interface EntityDao<E> { 

void persist(E e) throws Exception; 

void remove(Object id) throws Exception; 

E findById(Object id) throws Exception; 
} 

EntityDaoImpl:

public class EntityDaoImpl<E> implements EntityDao<E> { 

@PersistenceContext(unitName="UnitPersistenceName") 
protected EntityManager entityManager; 

protected E instance; 
private Class<E> entityClass; 

@Transactional 
public void persist(E e) throws HibernateException{  
    getEntityManager().persist(e); 
} 
    @Transactional 
public void remove(Object id) throws Exception{  
    getEntityManager().remove((E)getEntityManager().find(getEntityClass(), id)); 
} 

public E findById(Object id) throws Exception {  
    return (E)getEntityManager().find(getEntityClass(), id);  
} 
    public EntityManager getEntityManager() { 
    return entityManager; 
} 
public void setEntityManager(EntityManager entityManager) throws Exception{ 
    this.entityManager = entityManager; 
} 

    public Class<E> getEntityClass() throws Exception{  
    if (entityClass == null) { 
      Type type = getClass().getGenericSuperclass(); 
      if (type instanceof ParameterizedType) 
      { 
       ParameterizedType paramType = (ParameterizedType) type; 
       if (paramType.getActualTypeArguments().length == 2) { 
        if (paramType.getActualTypeArguments()[1] instanceof TypeVariable) { 
         throw new IllegalArgumentException(
          "Can't find class using reflection"); 
        } 
        else { 
         entityClass = (Class<E>) paramType.getActualTypeArguments()[1]; 
        } 
       } else { 
        entityClass = (Class<E>) paramType.getActualTypeArguments()[0]; 
       } 
      } else { 
       throw new Exception("Can't find class using reflection"); 
      } 
     } 
     return entityClass; 
    } 
} 

Und Sie wie folgt verwenden können:

public interface UserDao extends EntityDao<User> { 

} 

und

public class UserDaoImpl extends EntityDaoImpl<User> implements UserDao{ 

} 
+0

All dieser Code ist im Wesentlichen, was Spring Data Jpa bietet Ihnen: http://www.springsource.org/spring-data/jpa – bh5k

+1

Es gibt tatsächlich ein paar Fehler mit diesem Code, Sie möchten nicht Ihre Transaktionen in die DAO/Repository-Ebene. – bh5k

1

Erstellen eines separaten Service für jedes Modell ist eine Möglichkeit, es zu tun, und Ich habe reale Anwendungen gesehen, die das tun, aber ich empfehle es nicht. Es ist Overkill für den einfachen Fall CRUD und ist nicht hilfreich für die komplexeren Fälle (wo Sie eigentlich eine Transaktion über mehrere DAO-Aufrufe erstrecken soll). Es hinterlässt eine Menge Code, der nicht viel bewirkt. Die DAOs können mithilfe von Spring Data angegeben werden. Die Dienste werden als Textbausteine ​​ausgeführt, wobei jede Methode einen Aufruf an ein DAO überträgt. Die Feder sollte dazu beitragen, den Standard zu reduzieren, anstatt ihn festzulegen.

Wenn Sie eine vollständige CRUD-Anwendung haben, können Sie legitimerweise auf Dienste verzichten, @Transactional auf die DAOs setzen und das DAO vom Controller aus aufrufen. Wenn der Dienst sein Gewicht nicht abzieht, wird er beseitigt.

Wenn Sie tatsächlich Geschäftslogik in der Anwendung haben, wenn ein Benutzer etwas aufruft, das Aufrufe an verschiedene DAOs umfassen kann, sollten diese Aufrufe normalerweise innerhalb der gleichen Transaktion stattfinden, so dass wenn eine Sache fehlschlägt alles zurückgesetzt wird. (Auch das Erstellen einer Transaktion ist relativ teuer und wenn Sie einen Controller haben, der verschiedene Dienste für verschiedene Entitäten aufruft, dann ist das langsam.) Da sind Dienste nützlich, der Dienst spezifiziert die Low-Level-Anwendungsfälle, die der Benutzer wünscht ausgeführt werden und ermöglicht die Angabe des Transaktionsverhaltens.

Für den Fall CRUD würde ich lieber ein Werkzeug wie Grails oder Play oder Rails oder etwas zum Schreiben von Java mit Spring MVC verwenden. Grails zum Beispiel generiert Sichten und Controller für Sie, bietet grundlegenden Datenzugriff über GORM (es gibt also keine DAOs zum Schreiben), und Sie können Services leicht für die Fälle angeben, in denen Sie sie benötigen.

Verwandte Themen