带弹簧数据的六边形结构

我将开始一个新项目来学习弹簧靴,弹簧数据和六边形架构。根据我的理解,六边形架构旨在将核心层或域层与数据库操作(基础架构层)分开。我已经看到了此体系结构的以下项目结构。

核心层具有:

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

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

基础结构层必须实现的存储库>接口。

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

Spring数据有一个非常有用的方法来实现CRUD操作:

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

但是,我认为如果我使用 spring 数据,如果 UserRepository 是核心层的一部分,则 JPA 实体将不会成为基础架构层的一部分。这意味着核心实体将毫无用处。我应该创建另一个属于核心层的用户存储库界面,还是缺少某些内容?

更新:

我对 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实体映射到域实体中,也许我需要使用另一个类(和适配器?)来执行该映射。这种方法是否正确还是有其他方法?很抱歉这篇文章很长,我希望我已经把自己说清楚了。


答案 1

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

您尝试做的是创建“辅助端口”和“辅助适配器”。

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

jpa 实体不能是您的域。它描述了数据在数据库中的存储方式。因此,jpa 实体不能在“辅助端口”中使用,只能使用您的域。

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

但是,如果您真的想使用适当的六边形架构,请小心。Hibernate和后来的JPA的强大之处在于jpa实体是你的领域。它使事情变得简单(和困难)。通过将域从实体中分离出来,您将失去延迟加载机会,清除交易边界,孤立删除......也许你应该做一个交易,把jpa放在核心层。

希望对您有所帮助


答案 2

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

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

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

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


推荐