Spring 引导数据 jdbc 实现与同一实体的多对多关系

Spring boot data jdbc implement Many to Many relationship with same entity

如何使用 spring 数据 jdbc 对同一实体的多对多关系建模。我有一个场景,其中一个任务可以依赖于其他几个任务,同时该任务有依赖项但它是同一个对象。我以前用 jpa

做过这个
@JoinTable(
    name = "task_dependencies",
    joinColumns = @JoinColumn(name = "dependent_process"),
    inverseJoinColumns = @JoinColumn(name = "depends_on_process")
)
private final Set<AsyncTask> dependencies = new HashSet<>();

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "dependencies")
private final Set<AsyncTask> dependents = new HashSet<>();

在您的示例中,AsyncTask 是一个聚合及其自己的聚合根。 因此,从一个 AsyncTask 到另一个的引用被认为是聚合之间的引用。

在 Spring 数据 JDBC 中(并且在领域驱动设计中也推荐)对其他聚合的引用将作为 ID 实现,而不是实际的 Java 引用。

对于映射 table,您需要一个单独的小实体,它成为关系一侧聚合的一部分。

您可以使用 AggregateReference 而不是 Id,以避免到处都是 Long 值。

完整的模型可能如下所示:


@Table
class AsyncTask {

    @Id
    Long id;
    String name;

    @MappedCollection(idColumn = "FROM_ID")
    Set<DependentTask> dependents = new HashSet<>();

    AsyncTask(String name) {
        this.name = name;
    }

    public void addDependent(AsyncTask task) {
        dependents.add(new DependentTask(task.id));
    }
}

@Table
class DependentTask {
    @Column("TO_ID")
    AggregateReference<AsyncTask, Long> id; // this is the Id of the dependent task, note that it is not marked with `@Id`

    DependentTask(Long id) {
        this.id = AggregateReference.to(id);
    }
}

并像这样使用:

AsyncTask one = repo.save(new AsyncTask("one"));
AsyncTask two = repo.save(new AsyncTask("two"));

AsyncTask three = new AsyncTask("three");
three.addDependent(one);
three.addDependent(two);
repo.save(three);

one.addDependent(two);
repo.save(one);

two.addDependent(two);
repo.save(two);

底层数据库模式如下所示:

CREATE TABLE ASYNC_TASK (
    ID INTEGER IDENTITY PRIMARY KEY,
    NAME VARCHAR (200) NOT NULL
);

CREATE TABLE  DEPENDENT_TASK (
    FROM_ID INTEGER NOT NULL REFERENCES ASYNC_TASK(ID),
    TO_ID INTEGER NOT NULL REFERENCES ASYNC_TASK(ID)
);

complete source code is on GitHub.

有关该主题的更多信息,请阅读 Spring Data JDBC, References, and AggregatesSpring Data JDBC - How do I make Bidirectional Relationships?