【问题标题】:hexagonal architecture with spring data带有弹簧数据的六边形结构
【发布时间】:2018-03-12 13:33:13
【问题描述】:

我要开始一个新项目,学习spring boot、spring data和六边形架构。据我了解,六边形架构旨在将核心或域层与数据库操作(基础设施层)分开。我已经看到了这个架构的以下项目结构。

核心层有:

服务-> 逻辑去向(接口及其实现)。

实体 -> 这些将在整个应用程序中使用。

Repository-> 基础设施层必须实现的接口。

基础设施层实现了存储库接口、JPA 实体、对数据库的调用(休眠)以及将 JPA 实体转换为核心实体(映射器?)的某种功能。

Spring data 有一种非常有用的方式来实现 CRUD 操作:

public interface UserRepository extends JpaRepository<User, Integer> {
}

但是,我认为如果我使用 spring 数据,如果 UserRepository 是核心层的一部分,那么 JPA 实体将不会成为基础设施层的一部分。这意味着核心实体将毫无用处。我应该创建另一个属于核心层的 UserRepository 接口还是我缺少什么?

更新:

我对使用 spring 数据的担忧来自于我必须在域中包含 JPA 实体,这在理论上会违反六边形架构。

所以我正在考虑将域实体与 JPA 实体分开。但是如果我这样做,我不知道 Spring Data 的存储库应该去哪里,并且还找到一种将 JPA 实体转换为域实体的方法。

为了更好地说明,我将假设我需要从我的应用程序连接到数据库以读取用户表。

这可能是域实体:

public class UserDomain{
  private String name;
  ....//More fields, getters, and setters.

据我了解,服务应该包含逻辑并操作域实体。

public interface UserService{
  public void create(UserDomain user);
  ...

实现:

public class UserServiceImpl implements UserService{
  public void create(UserDomain user) {
     ... //Calling the repository(Spring Data Repository?)

以上以及存储库接口是我认为的域(如果我错了,请纠正我)。接下来,基础设施由 JPA 实体组成

@Entity
@Table(name="users")
public class User{
  @Column(name="name")
  private String name;
  ... // More Fields, getters, and setters

我认为我调用 Spring Data 的接口应该在基础设施部分,因为稍后我需要将 JPA 实体映射到域实体中,也许我需要使用另一个类(和适配器?)来进行映射.这种方法正确还是有其他方法?抱歉发了这么长的帖子,我希望我已经说清楚了。

【问题讨论】:

    标签: java spring spring-data-jpa hexagonal-architecture


    【解决方案1】:

    这是一篇关于如何将数据库连接到应用程序的好文章:http://www.dossier-andreas.net/software_architecture/ports_and_adapters.html

    您要做的是创建一个“辅助端口”和“辅助适配器”。

    “辅助端口”(= 接口)描述了要做什么,但没有框架依赖项。 “辅助适配器”(= 实现)使用 jpa-repositories。

    jpa-entity 不能是您的域。它描述了数据如何存储在数据库中。因此,jpa-entity 不能在“辅助端口”中使用,只能在您的域中使用。

    “辅助适配器”需要将您的域转换为 jpa-entities。

    不过,如果您真的想使用正确的六边形架构,请小心。 Hibernate 和后来的 JPA 的强大之处在于 jpa-entity 是您的域。它使事情变得更简单(也更难)。通过将域与实体分开,您将失去延迟加载机会、清除事务边界、孤儿删除……也许您应该进行权衡并将 jpa 放入核心层。

    希望对您有所帮助

    【讨论】:

    • 所以没有解决方案来保持延迟加载机会使用正确的六边形架构?我对此感到绝望!
    • 在我看来,这些都是框架的问题。他们为您提供骨架,您所要做的就是将自己包裹在其中,您与他们的决定息息相关。毫无疑问,hibernate 是一个强大的工具。
    【解决方案2】:

    我对你的问题有点困惑。您谈论了很多关于层的内容,而我认为关于六边形架构的“文章”仅使用该术语(几乎?)来描述不该做什么。

    Spring Data 非常适合六边形方法:实体构成您的核心域,存储库接口构成面向数据库的 API。请注意,实现(在核心域之外,主要由 Spring Data 本身提供)取决于接口,而不是相反)。服务和/或控制器构成一个或多个面向用户的 API。

    有一些违反六边形架构规定的规则:实体和存储库上的注释。它们位于核心域内,但依赖于作为 JPA 或 Spring Data 的一部分的数据库访问的使用/实现。

    JPA 本身进一步违反了六边形架构,因为持久性实现的行为可能会严重泄漏到您的域中,因为如果您使用托管实体,任何更改都会自动跟踪并最终持久化,而无需调用持久性 API。此外,对持久层的更改(例如刷新策略的配置)可能会完全改变 API 的行为。

    【讨论】:

      【解决方案3】:

      为了补充汤姆的答案,我找到了以下选项:

      • 创建一个与 spring 数据中相同结构的接口,问题是您必须在服务中进行转换。
      • 创建一个具有未定义函数的抽象类,为您提供数据,然后在 spring 服务中,从该类继承并使用 jpa 存储库实现功能,问题是您不会将存储库与服务分开.
      • 不要为存储库创建接口,在域中创建一个为您提供数据的类/接口(它将是您的存储库),该功能是您在 spring 服务中继承的,将具有图形存储库,但不是注释,如果您使用 JPA 存储库,例如。

      Domain.Service 使用 Domain.RepositoryApplication.repository 继承自 Domain.repository 并使用 JPA 存储库,Aplication.service 继承自 Domain.service 并使用 Domain.repository

      上一个的问题是复杂性和使用spring的依赖注入为应用程序的服务而玩

      另一个问题是实体,在一些项目中我只是使用jpa,在另一个我只用getter和setter做了一个接口,后者有点麻烦

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-22
        • 1970-01-01
        • 1970-01-01
        • 2019-06-15
        • 2018-10-06
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多