【问题标题】:In which layer do I access database in a MVC design [closed]在 MVC 设计中,我在哪一层访问数据库 [关闭]
【发布时间】:2015-07-11 23:44:02
【问题描述】:

我有一个关于 mvc 应用程序中的数据库访问的问题。我的数据库访问逻辑应该放在哪里?

应该放在每个模型中吗? (如果我有 Person 模型)

Person p = new Person();
p.save();

应该放在每个控制器中吗? 还是应该只创建一组不同的类来执行数据库逻辑,这意味着除了模型、视图和控制器之外我还有一个额外的层?

这是怎么做到的? 如果使用 ORM 怎么办?

【问题讨论】:

  • 这个问题太宽泛了。什么样的应用程序——这是一个 GUI 还是一个 Web 应用程序?涉及的数据域有多大,您的操作有多复杂?
  • 这是一个网络应用程序。假设它是一个小型 Web 应用程序

标签: java database model-view-controller


【解决方案1】:

在MVC模式中,M代表模型,V代表视图,C代表控制器。一个常见的 MVC 应用程序进程是,一旦请求到来,控制器获取它并进行必要的处理,检索结果数据,然后将结果数据传递给视图进行渲染。视图层渲染后,通过图形用户界面显示给用户。

Controller 可以看成是一个指挥者,它控制着进程,但不好处理控制器中的数据检索。模型应该负责检索和组织数据。这意味着数据对象应该存储在Model而不是Controller中,Controller调用Model来检索数据对象。

对于您的情况,我的建议是它需要以下组件:

  1. PersonController,它调用PersonService.savePerson(Person person) 方法来保存数据(或者在其他情况下它检索结果)。我建议 Controller 层应该很薄。
  2. PersonService,它有方法savePerson(Person person),这个方法调用PersonDAO.savePerson(Person person)方法来保存/检索项目数据(这里它保存数据),也许还有其他处理。业务逻辑到此为止。
  3. PersonDAO,它有几个处理Person对象的方法(如savePerson(Person person)getAllPersons()),在这一层处理数据库。但是这些方法应该独立于业务逻辑(因为业务逻辑应该在PersonService处理)。
  4. Person 对象,它是value object,它只是定义了Person 应该具有的属性,例如nameage 等,以及get/set 方法,用于通过不同层传递数据。它根本不处理数据库。

对于不复杂的应用,Service层不是很必要,可以集成到Controller层,也就是说PersonController就可以了。

【讨论】:

  • 这意味着我有 Person.java PersonService.java 和 PrsonDAO.java。那么有服务层和DAO层吗?
  • 服务层和DAO层有什么区别?
  • @DesirePRG 服务/控制器层处理业务逻辑(如登录,首先检查用户是否存在,其次检查用户名/密码是否对齐),DAO 层处理数据库,不包含业务逻辑(DAO层提供了isUserExistscheckNamePass方法,但是你看这2个方法和业务逻辑无关)。
【解决方案2】:

其他人指出数据库访问是一个Controller功能,但我建议您创建一个新的库项目来处理数据库交互。通常,这将具有类似“customerService.jar”的名称 - 即它封装了您想对客户做的所有事情。这将简化您的应用程序,并大大增加代码的可重用性。

这将是通过方法:

  • 定义一个公开业务级别操作的接口(例如,changeUserRole(long userId, Role newRole)ma​​kePayment(long accountId, BigDecimal amount),而不是 CRUD 方法updateUser(User user) 等。通常,接口公开的一些方法看起来像 CRUD 方法,但可能在数据库端做更多的事情(例如检查帐户状态,维护审计表)。李>
  • 在这一层实现您的业务逻辑。纯粹主义者会说业务逻辑应该有一个单独的层,但这使得很难使用 SQL 工具(特别是连接)来有效地访问数据库。根据我的经验,需要将这两层结合起来以保持系统的简单性和高性能。
  • 使用 ORM 工具访问数据库并将业务对象映射到数据库。 (MyBatis 是我的最爱)。如果您的数据库准确地反映了您的业务模型,那么您可能不需要单独的 DAO 和业务对象。
  • 将 customerService 的实例注入 Web MVC 控制器。控制器的工作现在是验证用户输入、填充模型、将请求传递给 customerService 并将响应数据放回模型中。

因此,如果您的需求在未来发生变化(例如,您需要创建一个 IOS 或 Android 原生应用程序),您将拥有一个可重用的服务,可以很高兴地完成这项工作。同样,如果架构师坚持将其公开为 REST 或 SOAP 服务,您只需添加“粘合逻辑”即可实现 REST 或 SOAP 服务。

此外,在 Web 单元测试中模拟 customerService 很容易。

祝你好运!

【讨论】:

    【解决方案3】:

    最好将代码隔离并根据它们的行为对其进行分组。模型类可以用作数据库的逻辑表示。您应该有一些实用程序/帮助程序类来执行您的数据库活动,并且控制器应该与它们交互。

    理想情况下,您应该拥有与数据库中的表数量一样多的模型类(如果不是更多的话)。

    当您使用 ORM 时,连接和映射(一旦声明)由框架处理,您专注于业务逻辑。

    【讨论】:

    • 所以我应该有一个额外的层来访问这个数据库?
    • 理想情况下,您应该根据类执行的功能对类进行隔离/分组,如果这意味着添加额外的层,请继续。
    【解决方案4】:

    在使用 Spring 或 Jersey 等框架(您应该使用)的 Web 应用程序中,通常最好使您的“控制器”(HTTP 请求处理程序)尽可能简单,围绕包含您的服务层的服务层进行包装。数据库访问等业务逻辑。这使得测试变得非常简单,因为您可以直接测试业务逻辑,而无需复杂的 HTTP 请求,并且可以更轻松地在未来的更改(例如添加计划任务)中重用您的业务逻辑。

    当不只是简单的 CRUD 操作涉及到 Person 对象之类的东西时,我将创建一个 PersonService,其中包含根据业务操作表示的方法,并将该服务注入控制器。对于简单的 CRUD 操作,我通常直接从控制器中使用 Spring Data 存储库。

    【讨论】:

      【解决方案5】:

      在您的类文件中定义访问 Db 或执行与 DB 相关的操作的函数,我们将其称为模型,然后在 Controller 中使用该类对象访问该函数。控制器只是一组函数,它们为我们提供数据库结果并将这些结果分配给控制器中的变量,并在您的前端视图中访问这些变量

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-24
        • 2016-08-18
        • 1970-01-01
        • 2010-12-03
        • 2012-06-06
        • 1970-01-01
        相关资源
        最近更新 更多