在领域驱动设计中,当在聚合内创建新对象时,创建数据库条目的最佳方法是什么?
举个例子,考虑一个代表大学学生的
Student
实体。学生参加课程,这些课程是学生聚合的一部分,作为 CourseParticipation
值对象列表。这些对象跟踪学生的参与率和最终成绩。当学生注册新课程时,我们会致电 Student.participateIn(Course)
。在Java中,它看起来像这样:
public class Student {
private List<CourseParticipation> courseParticipations;
public void participateIn(Course course) {
// Business logic: Check if the student is allowed to participate
courseParticipations.add(new CourseParticipation(this, course));
}
}
现在新的课程参与必须存储在数据库中名为
course_participations
的表中。在我的应用程序中执行此操作的常用方法是调用 CourseParticipationRepository.save(CourseParticipation)
。当在聚合内创建对象时,如何进行此调用?
我能想到或在互联网上读到的选项:
将
CourseParticipationRepository
注入 Student
并保存在 participateIn(Course)
方法中。
好:
student.participateIn(course)
即可完成坏:
Student
对象...为每个对象提供对存储库单例的引用是一个好主意吗?返回未保存的
CourseParticipation
对象并让调用者保存它
好:
坏:
CourseParticipation
对象让
StudentRepository.save(Student)
为每个 CourseParticipationRepository.save
对象 调用 CourseParticipation
好:
CourseParticipation
对象不会暴露给 participateIn
坏:
StudentRepository
需要访问CourseParticipation
对象的内部列表,否则这些对象不会被暴露重新设计数据库表或使用对象数据库
我在很多有关领域驱动设计的文章中读到了这个建议。这对于绿地项目来说很有意义。但这不是我正在开发的应用程序的一个选项。
最好或最常见的选择是什么?还有其他解决办法吗?
聚合不应该关心表结构。这(以及聚合是一致性单位的要求)最终意味着第三种方法就是方法。
StudentRepository 需要访问 CourseParticipation 对象的内部列表,否则该对象不会被公开
课程参与列表是
Student
的一部分。拯救学生意味着拯救参与。
如果聚合映射到许多数据库表,则保存方法可能会变得非常复杂 避免不必要的数据库调用(即保存未更改的条目)可能很困难
不幸的是,这就是休息时间。
DDD 聚合基本上采用对象存储(或事件存储,如果是事件源),因为该抽象与保存/检索聚合所需的最低功能相匹配。关系模式,尤其是追求更高范式的关系模式,将会带来开销/复杂性。