14

我要开始一个新项目,学习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 实体映射到域实体中,也许我需要使用另一个类(和适配器?)来进行映射。这种方法正确还是有其他方法?抱歉发了这么长的帖子,我希望我已经说清楚了。

4

3 回答 3

20

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

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

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

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

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

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

我希望你发现这对你有帮助

于 2017-10-10T10:04:56.327 回答
6

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

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

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

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

于 2017-10-02T08:20:54.637 回答
1

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

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

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

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

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

于 2018-07-16T18:53:49.267 回答