【问题标题】:Service and DAO classes are doing same thing. Why would you need them both?服务和 DAO 类做同样的事情。为什么你需要他们两个?
【发布时间】:2014-07-05 18:18:18
【问题描述】:

大家好,我是 Spring 新手。只是有一个疑问。服务和 DAO 类做同样的事情吗?为什么你需要他们两个?除此之外,我们可以将控制器直接连接到我们的 Dao 方法,并从中获取数据。究竟需要什么服务层。我浏览了几个门户网站,其中一些人告诉服务层提供模块化,很少有人提到它也是出于安全目的。我仍然很困惑 谁能为这个查询提供一个明确的答案?

【问题讨论】:

  • 所有与 SQL 无关的问题——安全性、输入验证、日志记录、“业务逻辑”——必须进入服务层。

标签: java spring hibernate


【解决方案1】:

在事务和回滚的情况下,服务层是必要的。假设你有一个案例 一种执行多次更新或删除的方法。在这种情况下,您的控制器可能不支持事务,但在服务层中,spring 为您提供了提交和回滚的方法

让服务层成为 DAO 的包装器是一种常见的反模式。在您给出的示例中,它肯定不是很有用。使用服务层意味着您可以获得以下好处:

您可以清楚地区分最好在控制器中完成的 Web 类型活动和与 Web 无关的通用业务逻辑。您可以将与服务相关的业务逻辑与控制器逻辑分开测试。

  • 您可以指定事务行为,因此如果您有调用 多个数据访问对象
  • 您可以指定它们发生在同一事务中
  • 您可以嵌套服务,这样如果一个服务具有不同的事务性 行为(需要自己的事务),您可以强制执行。
  • 您可以使用 postCommit 拦截器来执行通知内容,例如 发送电子邮件,这样就不会破坏控制器。

通常,我的服务包含单一类型用户的用例,服务上的每个方法都是该用户将执行的单个操作(在单个请求-响应周期中完成的工作),与您的例如,其中通常不止一个简单的数据访问对象调用。

【讨论】:

    【解决方案2】:

    服务层的目的是使用 DAO(s) 来实现您的业务逻辑。 我已经获得了以下服务层的一些好处

    • 服务层可以使用事务来执行原子操作。在 DAO 层中使用事务没有意义(对于复杂的用例),因为操作中可能涉及多个实体。

    • 在服务层的帮助下,我们可以将会话范围扩展到请求而不是每次操作的会话。

    • Service Layer 可用于处理业务特定的异常,并可以抛出可用于显示错误页面的新业务异常。从 DAO 抛出业务特定异常,例如 BadCredentials 或 InvalidInput,增加了 DAO 验证用户名和密码的额外责任。理想情况下,DAO 仅用于与数据库通信,所有业务逻辑都应位于服务层。

    • 一个服务可以使用多个服务来执行工作流并允许代码重用。

    例如用例

    这是 DAO 的简单实现,在并发访问期间可能会失败 到同一数据库行。 假设有两个操作 A 和 B。操作 A 和 B 想要创建具有相同用户名的用户(如果用户名不存在)。

    操作 A 开始 --> getUser("abc") 返回 null ---> 因此 createUser(abc)。

    操作 B 开始 ---> getUser("abc") return null 因为事务 A 尚未创建用户 abc---> 因此 createUser(abc),如果我们使用,这将引发重复主键的数据库异常用户名作为主键,或者如果我们使用代理键,我们可以有两个用户具有相同的用户名,因为操作 A 在之前的事务中创建了用户 abc。

    public class UserDao{
    
    
    public User getUser(String Username){
    
        User user = null;
        Session session = SessionFactory.OpenSession();
        Transaction tx = session.beginTransaction();
    
        // Some logic here...//
        tx.commit();
        session.close();
        retur user;
    }
    
    public User createUser(User user){
    
        Session session = SessionFactory.OpenSession();
        Transaction tx = session.beginTransaction();
        // Some logic here...//
        tx.commit();
        session.close();
    }
    
    }
    
    
    public class NewUserDao{
    
    
    public User getUser(String Username){
    
        User user = null;
        Session session = SessionFactory.getCurrentSession();
        // Some logic here...//
        return user;
    }
    
    public User createUser(User user){
    
        Session session = SessionFactory.getCurrentSession();
        // Some logic here...//
        return user;
    }
    
    }
    
    public class UserService{
    
    New UserDao newUserDao; //Dependecy injection
    
    @Transactional
    public User createUser(User user){
    
    if(newUserDao.getUser(user.getUserName())== null){
        newUserDao.createUser(user);
    }
    
    }
    
    }
    

    【讨论】:

      【解决方案3】:

      您应该将所有对数据库的访问权限都放在 DAO 中,并且您不应该将业务逻辑放在此处。所有逻辑都应该放在服务中,服务应该调用 DAO 来查询数据库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-16
        • 1970-01-01
        • 2017-02-18
        • 2019-09-08
        • 2017-03-06
        • 2019-12-30
        相关资源
        最近更新 更多