在 MVC 设计中我在哪一层访问数据库

In which layer do I access database in a MVC design

我对 mvc 应用程序中的数据库访问有疑问。我的数据库访问逻辑应该放在哪里?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

方法是:

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

因此,如果您的需求在未来发生变化(例如,您需要创建一个 IOS 或 Android 本机应用程序),您将拥有一个可重复使用的服务,它将很乐意完成这项工作。同样,如果架构师坚持将其暴露为 REST 或 SOAP 服务,您只需添加 "glue logic" 即可实现 REST 或 SOAP 服务。

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

祝你好运!