简体   繁体   English

OneToMany Spring数据JDBC

[英]OneToMany Spring Data JDBC

I want to model a OneToMany Relation with Spring Data JDBC. 我想用Spring Data JDBC建模OneToMany Relation。 I´ve read on this very useful blog https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates that you should use references when you want to model ToMany Reference: 我在这个非常有用的博客上阅读了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. 因此,任何“多对一”和“多对多”关系都必须通过引用id来建模。

So I have this scenario: 所以我有这个场景:
One Student can have multiple Registration . 一名Student可以进行多次Registration And one Registration can have exactly one Student . 一个Registration只能有一个Student If you delete Registration the assigned Student should not get deleted cascading. 如果删除Registration ,则不应将已分配的Student删除级联。
I ended up with this modelling: 我最终得到了这个建模:

@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<>();

}

My question is whether my modeling is correctly implemented? 我的问题是我的建模是否正确实施?

You are quoting the article talking about "Many-To-X" but you talk yourself about "X-To-Many". 你引用的文章是在谈论“很多到X”,但你会谈论“X-To-Many”。 You can model a One-To-One or a One-To-Many relationship with a direct reference, or a List/Set/Map of entities. 您可以使用直接引用或实体的列表/集/映射来建模一对一或一对多关系。

What you should avoid are bidirectional relationships. 你应该避免的是双向关系。 While you probably can make them work with the approach you are using, you really shouldn't. 虽然你可能会让它们与你正在使用的方法一起工作,但你真的不应该这样做。

Which brings us to the question: How should this model look like? 这带来了一个问题:这个模型应该怎么样?

The central decision to make is how many aggregates are involved? 做出的核心决定是涉及多少聚合?

A Student certainly is an aggregate and the Student class is its aggregate root. Student肯定是一个聚合, Student类是它的聚合根。 It can exist on its own. 它可以独立存在。

But what about Registration ? Registration呢? I'd argue, it is probably part of the same aggregate. 我认为,它可能是同一集合的一部分。 The delete test is a good one. 删除测试很好。 If you delete a Student from the system, do the registrations of that Student still have value? 如果你删除一个Student从系统中,这样做的注册Student还有价值吗? Or should the disappear together with the Student ? 或者应该与Student一起消失?

As an exercise let's do both variants. 作为练习,让我们做两种变体。 I start with: Just one aggregate: 我开始:只有一个聚合:

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<>();
}

With this, you would have a single repository: 有了这个,您将拥有一个存储库:

interface StudentRepository extends CrudRepository<Student, Long>{}

I removed all the Lombok annotations since they aren't really relevant to the problem. 我删除了所有Lombok注释,因为它们与问题无关。 Spring Data JDBC can operate on simple attributes. Spring Data JDBC可以在简单属性上运行。

If Registration and Student both are aggregates it gets a little more involved: You need to decide which side owns the reference. 如果RegistrationStudent都是聚合,则会更多地涉及:您需要决定哪一方拥有该引用。

First case: The Registration owns the reference. 第一种情况: 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;
}

Second case: The Student owns the reference 第二种情况: 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;
}

Note that the RegistrationRef doesn't have a studentId or similar. 请注意, RegistrationRef没有studentId或类似的。 The table assumed for the registrations property will have a student_id column. registrations属性假定的表将具有student_id列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM