使用 JPA 时实现 MVC

Posted

技术标签:

【中文标题】使用 JPA 时实现 MVC【英文标题】:Implementing MVC when using JPA 【发布时间】:2009-07-07 08:41:57 【问题描述】:

正如我对 MVC 的理解,模型的逻辑也应该进入模型本身——使每个对象都成为一个自包含的实体。这意味着类的方法必须具有触发器和动作链。例如,通过在 Person 类中使用 setZipCode(zip) 可以触发一个操作,它会从 zip 到 city 表中查找邮政编码,然后同时设置 setCity(city)。

这一切看起来都很好,但是当您将一些 JPA 实现纳入图片时会发生什么?正如我所看到的,类的 setter 和 getter 必须清除所有额外的逻辑,因为 JPA 实现使用这些来构建对象。因此你不能在 setZipCode 中调用 setCity。我们已经通过将所有特定于模型的逻辑移动到控制器层来解决这个问题。在这种情况下,我们不会直接调用 Person,而是调用 PersonController.setAddressInfo(zip) 来处理两者,或者类似的东西。也许更好的选择是在执行此操作的实体内部具有瞬态函数。

所以这是我的问题:我是否错过了 MVC 或 JPA 原则中的一些基本内容,或者在使用 ORM 层时不能完全实现 MVC?如果通用 setter 和 getter 对于 JPA 来说是私有的,并且这些类将有一个单独的公共、瞬态 API 供开发人员使用,那会更好吗? (出于某种原因,Hibernate 似乎不介意访问私有方法。)

在我们在项目中使用 Hibernate 的 JPA 实现中,我的同事在另一个项目中使用了 EclipseLink,我最近一直在阅读一些关于 OpenJPA 的内容。

【问题讨论】:

【参考方案1】:

我的经验是,您可能必须在实际的 JPA 域对象和您的 MVC 框架控制器之间添加另一层。有关 JPA 的文献称它们为数据访问对象 (DAO) 理想情况下,JPA 业务对象只是 POJO(普通的旧 Java 对象),带有没有任何逻辑的 getter 和 setter,DAO 实现类似

的操作
List<Post> PostDao::searchPostsByDate(Date d);
void PostDao::save(Post p);

我使用的架构甚至在 DAO 层之上还有另一个服务层,其中 DAO 特定于一个域模型实体,服务类执行事务管理并调用相应的 DAO 方法。这些服务可以与多个 DAO 交互,以便该服务可以提供类似的方法

City MainService::getCityByZipCode(ZipCode zc);

我个人认为服务层不是强制性的,例如在您的 DAO 中使用 Springs @Transactional 注释并提供适当的方法,例如

@Transactional
City ZipCodeDAO::getCity(ZipCode z);

【讨论】:

【参考方案2】:

我使用将模型分成一个业务层,该层调用其他业务对象、控制事务和所有这些东西,以及值层(瘦 POJO)。

ORM 可以很好地与业务层集成,而不会破坏 MVC 范式。

JPA 版本如前所述工作。

问候!

【讨论】:

以上是关于使用 JPA 时实现 MVC的主要内容,如果未能解决你的问题,请参考以下文章

设置 Spring JPA 项目以在 MVC 项目中使用 - 创建 bean 时出错

Spting +Spring MVC+spring date jsp +hibernate+jq

如何使用 JPA 实现测试 DAO?

Spring MVC和Spring Data JPA之获取数据表数据放在List集合,显示在JSP页面

JPA 实现——哪一个最好用? [关闭]

如何在实现 Spring Data JPA AuditorAware 接口时获取 getUserPrincipal().getUserName()