【问题标题】:Responsibilities and use of Service and DAO Layers服务层和 DAO 层的职责和使用
【发布时间】:2012-11-26 23:05:41
【问题描述】:

我目前正在使用带有 Spring 插件和休眠的 Struts2 开发一个 Web 应用程序,当我查看在线示例时,我看到了 Service 和 DAO 层的使用,现在我想到了 Service 和数据访问对象的真正用途是什么层?如果 Service 层只是调用 DAO 层的方法来执行 CRUD 操作。直接调用DAO层的方法不是明智的吗?

我们来说说这个 Dao 和服务层的例子

人员服务

  @Transactional
    public class PeopleService {

        private PeopleDao pDao;

        public PeopleDao getPDao() { return pDao; }

        public void setPDao(PeopleDao peopleDao) { this.pDao = peopleDao;   }

        public void createPerson(String name){
            pDao.createPerson(name);
        }

        public List<Person> getPeople(){
            return pDao.getPeople();
        }

    }

人道

public class PeopleDao {

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session sess() {
        return sessionFactory.getCurrentSession();
    }

    public Person getPersonById(long id) {
        return (Person) sess().load(Person.class, id);
    }

    public void deletePersonById(long id) {
        sess().delete(getPersonById(id));
    }

    public void createPerson(String name) {
        Person p = new Person();
        p.setName(name);
        sess().save(p);
    }

    @SuppressWarnings("unchecked")
    public List<Person> getPeople() {
        return sess().createQuery("from Person").list();
    }

}

我的问题是,如果服务层仅由其代表 DAO 注入然后调用其方法,那么它们的真正用途是什么?

【问题讨论】:

标签: java jakarta-ee service architecture dao


【解决方案1】:

当您的业务逻辑比数据逻辑更复杂时,拥有这两层是个好主意。服务层实现业务逻辑。在大多数情况下,这一层必须执行更多操作,而不仅仅是从 DAO 对象调用方法。如果您想扩大您的应用程序,这可能是最好的解决方案。

假设您想要包含一个 City 实体并在 People 和 City 之间创建一种关系。这是一个例子:

@Transactional
public class PeopleService {

    ....
    private PeopleDAO pDAO;
    private CityDAO cDAO;

    ...

    public void createPerson(String name, String city)
     throws PeopleServiceException {
        Person p = new Person();
        p.setName(name);

        City c = cDAO.getCityByName(city);
        if (c == null) throw new ServiceException(city + " doesn't exist!");
        if (c.isFull()) throw new ServiceException(city + " is full!");
        c.addPeople(p);

        sess().save(p);
        sess().save(c);
    }

    ...
}

在此示例中,您可以实现更复杂的验证,例如检查数据的一致性。而且 PersonDAO 没有被修改过。

另一个例子:

DAO and Service layers with Spring

Definition of Service layer pattern

【讨论】:

  • POJO 不是实现了业务逻辑和其他验证吗? (而验证可以在客户端完成)
  • 嗯,这不是一个大例子。您可能会有一种使用一个或多个 DAO 的方法(例如 moveToOtherCity(person, city))。当然,在某些情况下,Service 和 DAO 层是相同的。关键是,总的来说,将这些层分开是一个很好的设计,因此您可以修改业务逻辑,但不能修改数据访问。
  • 当你说 POJO 我想你指的是 Person 类,对吧?还是 DAO? (并不总是 POJO 只是一个数据实体)。 Person类是一个Business(或Domain)对象,Service层实现Business(或Domain)逻辑。 DAO 通常只在业务对象中实现 CRUD 操作。
  • 我明白了,因为我的想法是域对象将相互协调以在服务层内部执行复杂的任务或计算(或数据转换),因此服务层仍然具有业务逻辑,同时域对象仍然有它的逻辑。服务层只是在协调它还是我错了?
  • 没错,双方都有业务逻辑。服务层会协调领域对象,所以它的业务逻辑比较复杂。域对象只知道它们自己的业务(或域)逻辑。
【解决方案2】:

如果您的应用程序将随着新的和不断变化的需求而增长,那么为您的软件的这两个不同方面(持久性->DAO、业务用例->服务)设置不同的层会非常适合您。

一方面是您的持久性模型及其关系、验证、事务和许多访问模式。

服务由具有非常不同粒度的业务用例驱动。一开始,您可能拥有非常简单的服务,这些服务除了调用 DAO 来交出从网页接收到的数据外,并没有做更多的事情。但这很可能会随着时间的推移而改变,服务将成长为协作对象的小型网络,这些网络可以为业务用例提供更多服务。如果你不使用 DAO,那么

  • 您的服务将包含处理查询对象、事务处理、验证的代码,所有这些都与实际业务需求无关
  • 服务代码看起来很乱,很难找出代码的哪些部分实际上与业务相关
  • 如果您随后更改持久性模型,最终可能会更改许多服务

此外,您不能轻松地对持久性模型进行单元测试,而只能在服务层上编写测试。不要忘记解耦和封装是减少变更影响的重要技术。

如果做得好,拥有 DAO 层不会引入太多实现开销,因此拥有它不会产生太多额外成本。它很快就会得到回报,您会很高兴拥有这个专用层。

查看这篇文章:http://codeblock.engio.net/?p=180。它还带有托管在 github 上的完整实现

【讨论】:

  • 老问题老回答,但我不得不说(不要误会);你的第一段是 YAGNI 的定义。是不是在@user962206 的情况下,他们不需要它,所以他们不应该创建那个服务层?
猜你喜欢
  • 2011-03-03
  • 2012-02-13
  • 2011-07-12
  • 2013-06-30
  • 2013-05-27
  • 2017-06-07
  • 2013-05-16
  • 1970-01-01
  • 2014-08-15
相关资源
最近更新 更多