Spring data、继承和mongodb

huangapple go评论78阅读模式
英文:

Spring data, inheritance and mongodb

问题

I am trying to understand how to do this right.

考虑以下情况:

Spring data、继承和mongodb

I want to persist this model to mongodb.

Option 1:
Should I persist Professor and Student to different collections (tables)?

Option 2:
Do I put them into a personsDao collection and save type of person and all other specialised properties (from Professor AND Student classes) in there. And when I retrieve the data from the db, I cast it into correct classes?

Which would mean, I just have one @Repository interface.

英文:

I am trying to understand how to do this right.

Consider the following situation:

Spring data、继承和mongodb

I want to persist this model to mongodb.

Option 1:
Should I persist Professor and Student to different collections (tables)?

Option 2:
Do I put them into a personsDao collection and save type of person and all other specialised properties (from Professor AND Student classes) in there. And when I retrieve the data from the db, I cast it into correct classes?

Which would mean, I just have one @Repository interface.

答案1

得分: 1

我认为两种选择都是有效的方法,但我更喜欢选项1。因此,在代码库中拥有抽象的人员类,并将教授和学生分成不同的表格(数据库层)使得以后处理自定义属性变得更容易。

英文:

I think both options are valid ways to go, but I prefer Option 1. So it's good to have the abstract person class on the code base and dividing professor and student into different tables (db layer) makes it much easier handling custom properties, later on.

答案2

得分: 1

Using Option 2 - Single PersonRepository:

显然,您可以使用选项2,因为这两个实体都具有您在Person(抽象类)中声明的相同属性。尽管在当前设计中应用这种方法是有道理的,但您也需要考虑未来的方面。

我把它们放入personsDao集合中,然后保存人员类型和所有其他专业属性(来自Professor和Student类)吗?

是的!您可以只使用一个存储库来存储两种类型的实体,并在Person中添加一个属性(type)。您的Person类应该如下所示,

public abstract class Person {
    // 共同属性
    private PersonType type;
    // getters/ setters
    public enum PersonType {
        STUDENT, PROFESSOR
    }
}

当我从数据库中检索数据时,我将其转换为正确的类吗?

将其转换为适当的类似乎是有前途的,但我建议您不要这样做。为什么呢?

假设您有getAllStudentssaveStudent等方法,可能它们看起来像这样,

public List<Student> getAllStudents() {	    
    return personRespository.findAllByType(PersonType.STUDENT)
                .map(person -> ((Student) person))
                .collect(Collections.toList());
}

public Student saveStudent(Student student) {
    Person person = new Person();
    person.setType(PersonType.STUDENT);
    
    // 将其他属性复制到person
    
    Person stored = personRespository.save(person);
    
    return ((Student) stored);
}

您对这些方法有什么看法?并且考虑所有其他CRUD方法以及Professor的方法。与此相反,只需使用Person并删除两个多余的实体。由于您有类型属性来区分它们,不再需要这两个子类,重构后的方法可能如下所示,

public List<Person> getAllStudents() {	    
    return personRespository.findAll();
}

public Person saveStudent(Person person) {
    person.setType(PersonType.STUDENT);
    return personRespository.save(person);
}

看起来好多了,对吧?

Using Option 1 - Separate Repository for Student and Professor:

我应该将Professor和Student持久化到不同的集合(表)中吗?

似乎管理两个实体的两个存储库是无关紧要和多余的,因为所有属性都相同,但实际上并非如此。当您必须在将来增强您的实体时,例如,Student必须与ScoreSheetProfessor相关联,或者Professor必须与Class相关联 - 您的设计是否能够适应?不可能,对吧?尽管这些对当前要求可能不是必需的,但您可以通过将它们分开来获得灵活性。此外,单独的存储库将更清晰,不再需要映射,每个实体将具有单一的责任。

public List<Student> getAllStudents() {	    
    return studentRespository.findAll();
}

public Student save(Student person) {
    return studentRespository.save(person);
}

选择哪种方法取决于您的需求和设计,但我更喜欢第一种选项。

英文:

Using Option 2 - Single PersonRespoitory

Apparently, you can use Option 2 as both entities have the same properties which you have declared in Person(abstract class). Though it makes sense to apply this approach in your current design, you need to consider thinking about future aspects as well.

> Do I put them into a personsDao collection and save the type of person and all other specialised properties (from Professor AND Student classes) in there.

Yes! you can use only one repository to store both types of entities and add a property (type) in your Person. Your Person class should look like this,

public abstract class Person {
 
    // common properties
	
	private PersonType type;
	
	// getters/ setters
	
	public enum PersonType {
	    STUDENT, PROFESSOR
	}
}

> And when I retrieve the data from the DB, I cast it into correct classes?

Casting into appropriate classes seems promising, but I suggest you do not so. Why?

Let's say you have getAllStudents, saveStudent methods and possibly they might be look like this,

public List&lt;Student&gt; getAllStudents() {	    
	return personRespository.findAllByType(PersonType.STUDENT)
	            .map(person -&gt; ((Student) person))
				.collect(Collections.toList());

}

public Student saveStudent(Student student) {
	Person person = new Person();
	person.setType(PersonType.STUDENT);
	
	//copy other properties to the person
	
	Person stored = personRespository.save(person);
	
	return ((Student) stored);
}

What do you think over these methods? And assume about all other CRUD methods along with Professor ones. Instead of doing so, just use Person and remove both redundant entities. As you have type property to distinguish among them, both children classes are no longer needed and refactored methods may look like this,

public List&lt;Person&gt; getAllStudents() {	    
	return personRespository.findAll();
}

public Person saveStudent(Person person) {
	person.setType(PersonType.STUDENT);
	return personRespository.save(person);
}

Seems much better, right?

Using Option 1 - Separate Repository for Student and Professor

> Should I persist Professor and Student to different collections (tables)?

It seems irrelevant and redundant to manage two repositories for two entities where all properties remain the same but it's not. When you have to enhance your entity in future, let's say, Student has to relate with ScoreSheet or Professor with Class - is it possible to adopt with your design? Not possible, right? Though these may not be necessary for the current requirement - you can have flexibility separating them. As well as, the separate repository will be cleaner, the mapping will be no longer needed, will have a single responsibility for each entity.

public List&lt;Student&gt; getAllStudents() {	    
	return studentRespository.findAll();
}

public Student save(Student person) {
	return studentRespository.save(person);
}

It depends upon your requirement and design to choose one of the approaches - but I prefer to go with the first option.

huangapple
  • 本文由 发表于 2020年1月6日 21:53:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/59613356.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定