OneToMany Spring 数据 JDBC
OneToMany Spring Data JDBC
我想用 Spring 数据 JDBC 建立一对多关系模型。我在这个非常有用的博客 https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates 上读到,当你想为 ToMany 建模时应该使用引用参考:
Therefore any Many-to-One and Many-to-Many relationship must be modeled by just referencing the 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<>();
}
我的问题是我的建模是否正确实施?
您引用的是 "Many-To-X" 的文章,但您自己却在谈论 "X-To-Many"。您可以使用直接引用或 List/Set/Map 实体对一对一或一对多关系进行建模。
你应该避免的是双向关系。虽然您可能可以让它们按照您正在使用的方法工作,但实际上不应该这样做。
这让我们想到了一个问题:这个模型应该是什么样子的?
要做出的核心决定是涉及多少聚合?
一个Student
肯定是一个聚合,Student
class是它的聚合根。它可以独立存在。
但是 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数据JDBC可以对简单的属性进行操作。
如果 Registration
和 Student
都是聚合,它会涉及更多一点:
您需要决定哪一方拥有参考。
第一种情况: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
没有 studentId
或类似的。为 registrations
属性 假设的 table 将有一个 student_id
列。
我想用 Spring 数据 JDBC 建立一对多关系模型。我在这个非常有用的博客 https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates 上读到,当你想为 ToMany 建模时应该使用引用参考:
Therefore any Many-to-One and Many-to-Many relationship must be modeled by just referencing the 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<>();
}
我的问题是我的建模是否正确实施?
您引用的是 "Many-To-X" 的文章,但您自己却在谈论 "X-To-Many"。您可以使用直接引用或 List/Set/Map 实体对一对一或一对多关系进行建模。
你应该避免的是双向关系。虽然您可能可以让它们按照您正在使用的方法工作,但实际上不应该这样做。
这让我们想到了一个问题:这个模型应该是什么样子的?
要做出的核心决定是涉及多少聚合?
一个Student
肯定是一个聚合,Student
class是它的聚合根。它可以独立存在。
但是 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数据JDBC可以对简单的属性进行操作。
如果 Registration
和 Student
都是聚合,它会涉及更多一点:
您需要决定哪一方拥有参考。
第一种情况: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
没有 studentId
或类似的。为 registrations
属性 假设的 table 将有一个 student_id
列。