如何为 Java 对象建模,该对象在 MySQL 数据库中保存自身的实例?

How do I model a Java object that holds instances of itself in a MySQL database?

我有一个 Web 应用程序,它有一个包含自身集合的对象。我正在为如何在 MySQL 数据库中对此建模而苦苦挣扎。它是一个包含子任务列表的任务对象。这是 class 的样子:

Task.java

public class Task{ 
    private int taskID;
    private String name;
    private String details;
    private List<Task> subTasks
    ...other properties

    public Task(int taskID, String name, String details){
        this.taskID = taskID;
        this.name = name;
        this.details = details;
        this.subTasks = new ArrayList<>();
    }

    Getters and Setters here...
}

通过一些研究和我自己的思考,我想出了一个可能的解决方案。我有它的 UML 图的图片,但不能 post 因为我刚加入而且我的 SO 代表还不够高。所以我尽力用下面的字符来展示它:

---------------------         -------------------
|       Task        |         |    SubTaskMap   |
--------------------- 1   __∞_|-----------------
| int taskID        |----|__∞_|int subTaskID    |
| String taskName   |         |int parentTaskID |
| String taskDetail |         -------------------
--------------------           

所以 subTaskID 和 parentTaskID 都是 table SubTaskMap 中的主键以及 table Task 中 taskID 的外键(同样,它们都是 [=35] 中的 Task 对象=]).据我所知,为了 运行 查询以查找与此设置上的 parentTaskID 关联的所有任务,我将不得不创建任务的别名 table。

我在 MS Access 中对这一切进行了建模,为了查询以获取与 parentTaskID 为 5 关联的所有任务,我在 Task.taskID 和 SubTaskMap.subTaskID 之间指定了一个连接,在别名 table Task_Copy 和链接 Task_copy.taskID 与 SubTaskMap.parentTaskID 的 SubTaskMap 得到一个 SQL 这样的查询:

SELECT Task.taskName, SubTask.parentTaskID
FROM Task AS Task_Copy INNER JOIN (Task INNER JOIN SubTask ON Task.taskID = SubTask.subTaskID) ON Task_Copy.taskID = SubTask.parentTaskID
WHERE (((SubTask.parentTaskID)=5));

那么这是解决这个问题的好方法还是有更好的方法?

感谢您的帮助!

如果一个子任务可以有多个父任务,那么这两个实例之间就有一个 many-to-many 关系。在这种情况下,您的解决方案是正确的(除了命名约定)。

如果您的任务只有一个父任务,那么您就有了 one-to-many 关系。在这种情况下,您将对父对象的引用存储在子对象中。所以你的 Task 会有一个父字段和一个子任务列表。 这当然使用ORM框架更容易操作。

主要区别在于,对于第一个,您有一个单独的 table 来保存关联,而对于第二个,您可以在同一 table(任务)的行中保存您的引用。

在男女关系中,您没有亲子关系。

我想你有一个案例Composite pattern。看看这个 post: What are the options for storing hierarchical data in a relational database?。我会选择邻接表:

将字段 ParentTaskId 添加到您的 table,并完全取消 SubTaskMap table。

如上文所述,如果子任务只能有一个父项,您可以向任务添加一个额外的列 table 并在其中跟踪 parent_task_id。 如果它是父级,则该列将没有值。

如果一个任务可以有多个父任务,那么您将需要一个不同的 table 来维持这种关系。