5

我想用 Spring Data JDBC 建模 OneToMany 关系。我已经阅读了这个非常有用的博客https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates,当你想建模 ToMany 参考时,你应该使用参考:

因此,任何多对一和多对多关系都必须仅通过引用 id 来建模。

所以我有这种情况:
一个Student可以有多个Registration. 一个Registration可以正好有一个Student。如果您删除Registration分配的Student不应该被删除级联。
我最终得到了这个模型:

@Data
@AllArgsConstructor(access = AccessLevel.PRIVATE, onConstructor = @__(@PersistenceConstructor))
public class Registration {

    private final @Id
    @Wither
    long registrationId;

    @NotNull
    private String electiveType;

    @NotNull
    private LocalDateTime created = LocalDateTime.now();

    @NotNull
    private StudentRegistrationReference studentRegistrationReference;

}

@Data
@AllArgsConstructor(access = AccessLevel.PRIVATE, onConstructor = @__(@PersistenceConstructor))
public class StudentRegistrationReference {
    private long student;
    private long registration;
}

@Data
@AllArgsConstructor(access = AccessLevel.PRIVATE, onConstructor = @__(@PersistenceConstructor))
public class Student {

    private final @Id
    @Wither
    long studentId;

    @NotNull
    @Size(min = 4, max = 20)
    private String userId;

    @NotNull
    @Min(0)
    private int matriculationNumber;

    @NotNull
    @Email
    private String eMail;

    private Set<StudentRegistrationReference> studentRegistrationReferences = new HashSet<>();

}

我的问题是我的建模是否正确实施?

4

1 回答 1

10

您引用的文章谈论“多对 X”,但您自己谈论的是“多对多”。您可以使用直接引用或实体的列表/集/映射来建模一对一或一对多关系。

您应该避免的是双向关系。虽然您可能可以使它们与您正在使用的方法一起工作,但您确实不应该这样做。

这给我们带来了一个问题:这个模型应该是什么样子?

核心决策是涉及多少个聚合?

AStudent当然是聚合,Student类是它的聚合根。它可以独立存在。

但是呢Registration?我认为,它可能是同一聚合的一部分。删除测试是一个很好的测试。如果你Student从系统中删除一个,它的注册Student还有价值吗?还是应该与 一起消失Student

作为练习,让我们做这两种变体。我开始:只有一个聚合:

class Registration {

    @Id private long Id;

    String electiveType;
    LocalDateTime created = LocalDateTime.now();
}

class Student {

    @Id private long Id;

    String userId;
    int matriculationNumber;
    String eMail;
    Set<Registration> registrations = new HashSet<>();
}

有了这个,您将拥有一个存储库:

interface StudentRepository extends CrudRepository<Student, Long>{}

我删除了所有 Lombok 注释,因为它们与问题无关。Spring Data JDBC 可以对简单的属性进行操作。

如果RegistrationStudent两者都是聚合,则涉及更多:您需要决定哪一方拥有引用。

第一种情况:Registration拥有引用。

class Registration {

    @Id private long Id;

    String electiveType;
    LocalDateTime created = LocalDateTime.now();

    Long studentId;
}

public class Student {

    @Id private long Id;

    String userId;
    int matriculationNumber;
    String eMail;
}

第二种情况:Student拥有引用

class Registration {

    @Id private long Id;

    String electiveType;
    LocalDateTime created = LocalDateTime.now();
}

class Student {

    @Id private long Id;

    String userId;
    int matriculationNumber;
    String eMail;

    Set<RegistrationRef> registrations = new HashSet<>();
}

class RegistrationRef {

    Long registrationId;
}

请注意,RegistrationRef没有 astudentId或类似的。为该registrations属性假定的表将有一student_id列。

于 2018-11-19T15:24:14.587 回答