38

我目前正在使用带有 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 注入然后调用其方法,那么它们的真正用途是什么?

4

2 回答 2

53

当您的业务逻辑比数据逻辑更复杂时,拥有这两个层是一个好主意。服务层实现业务逻辑。在大多数情况下,这一层必须执行更多操作,而不仅仅是从 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 没有被修改过。

另一个例子:

使用 Spring 的 DAO 和服务层

服务层模式的定义

于 2012-12-09T08:48:50.337 回答
13

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

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

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

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

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

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

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

于 2014-02-06T09:33:54.237 回答