2013-05-14 3 views
13

Я читал некоторые учебники, и я мог видеть, что большинство реализаций MVCHibernate и Spring - Dao, Услуги

основаны на:

1) интерфейс дао, например «IUserDao»

2) дао осущий этот интерфейс - "mySimpleUserDaoImpl"

3) сервисный интерфейс для: "упорства" IUserService

4) и осущий - «U serServiceImpl "

это лучшая практика? я имею в виду причину, по которой я задаю этот вопрос, потому что кажется избыточным иметь 30 сервисов с методами getXById(), deleteX (x), createX (x), которые делают более или менее одинаковыми.

пожалуйста, примите во внимание, что я использую весной 3 и 4 зимует, и я решил, я буду задавать этот вопрос, прежде чем я начать хлопнув мою клавиатуру с кодом

спасибо.

+2

Вы можете удалить префикс 'I' для интерфейсов. Пользователь не должен знать, что он получает интерфейс. Просто назовите их «UserDAO» и «UserService». – Bart

+0

Согласовано, оставьте I на интерфейсах. Я лично называю свои репозитории классов Dao, чтобы поддерживать его в соответствии с аннотациями Spring, но это не имеет значения. – bh5k

+1

Учебники для технологии обычно не связаны с бизнес-логикой, поэтому они не являются хорошими ссылками для этого. есть аналогичный вопрос, который может быть полезен для вас по адресу http://stackoverflow.com/q/3688664/217324 –

ответ

9

Если вы только начинаете разработку, изучите Spring JPA. Служба должна быть Хранилищем «один-ко-многим» (DAO). Но я бы также не создал весь этот шаблонный код вручную. Spring JPA устраняет основные функции CRUD и поиска, а также разбиение на страницы.

Here is a video, который проходит через всю конфигурацию для Spring, JPA, Hibernate и заканчивает Spring Data JPA, показывая вам весь код шаблона, который исключается.

Для использования Spring Data JPA, ваш интерфейс хранилища заканчивается существо:

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); 
} 

, а затем конфигурации XML для использования Spring Data JPA:

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

Все шаблонного кода теперь обрабатывается для тебя. Вам больше не нужно создавать базовый класс репозитория с методами поиска и базовыми функциями CRUD. Интерфейс JpaRepository предлагает множество приятных функций, и вы ничего не делаете для реализации.

+1

Еще одна вещь, касающаяся уровня сервиса - это то, где должно начинаться ваше @Transaction.Поэтому, если вы хотите откат транзакции через несколько репозиториев, уровень обслуживания - это место, где вы это делаете. Вот почему Сервис должен быть «один ко многим» с репозиториями. – bh5k

1

Нет необходимости иметь 30 уровней обслуживания или 30 уровней dao. Вы должны указать слои, не считая Entity wise, но функциональность бизнеса wise.there может быть 5 или 6 объектов, релевантных для определенной функции, и это должно быть в одном слое. Но все же вам придется иметь getXById(), deleteX (x), createX (x) в этих избыточных слоях, если они необходимы.

4

Необходимо иметь dao, daoImpl, service, serviceImpl для каждой модели.

  • UserDao
  • UserDaoImpl
  • UserService
  • UserServiceImpl

Вы можете использовать общий класс EntityDaoImpl АНФ inteface EntityDao, как это:

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; 
    } 
} 

И вы можете использовать так:

public interface UserDao extends EntityDao<User> { 

} 

и

public class UserDaoImpl extends EntityDaoImpl<User> implements UserDao{ 

} 
+0

Весь этот код по сути является тем, что Spring Data Jpa предоставляет вам: http://www.springsource.org/spring-data/jpa – bh5k

+1

На самом деле существует несколько ошибок с этим кодом, вы не хотите запускать свои транзакции в уровень DAO/Repository. – bh5k

1

Создание отдельной службы для каждой модели один из способов сделать это, и Я видел приложения реального мира, которые это делают, но я не рекомендую это делать. Это избыток для простого случая CRUD и бесполезен для более сложных случаев (когда вы действительно хотите, чтобы транзакция охватывала несколько вызовов DAO). Это оставляет вам много кода, который мало что может сделать. DAO можно указывать с использованием Spring Data, сервисы будут шаблонами с каждым методом, заключающим вызов DAO. Весна должна помочь уменьшить шаблон, в отличие от его мандата.

Если у вас есть полностью CRUD-приложение, то вы можете законно обойтись без сервисов, поставить @Transactional на DAO и вызвать DAO из контроллера. Если сервис не тянет его вес, избавиться от него.

Если у вас есть реальная бизнес-логика в приложении, тогда, когда пользователь вызывает что-то, что может включать вызовы в разные DAO, эти вызовы обычно должны выполняться в рамках одной и той же транзакции, чтобы, если одна вещь не удалась, все откатывается. (Также создание транзакции относительно дорогое, и если у вас есть контроллер, делающий вызовы для разных сервисов для разных объектов, то это будет медленным.) То есть, когда услуги пригождаются, служба указывает низкоуровневые варианты использования, которые пользователь хочет выполнять и разрешать транзакционное поведение.

Для случая CRUD я бы предпочел использовать такой инструмент, как Grails или Play или Rails, или что-то другое для написания Java с Spring MVC. Например, Grails создаст для вас представления и контроллеры, обеспечит базовый доступ к данным через GORM (поэтому нет DAO для написания), и это позволит вам легко указывать службы для тех случаев, когда вы считаете, что они вам нужны.

Смежные вопросы