前言
這周做的是alice專案中的一個bug,由於重新分班後,原班級沒有學生,對於原班級的某一課程成績分析也就沒有了。
比如說我原來是計算機1806班的(計算機專業一共9個班,分別是計算機1801-計算機1809班),由於大專業分流成小專業,我被分為了軟體181班,如果班級和學生是一對多的關係,此時計算機1806班已經沒有學生了,但是成績分析是對一個班的某一課程安排的成績分析,需要獲取這個班所有學生這個課程安排的成績,導致成績分析不能得到所有學生相關成績。
解決
我一開始認為改實體間關係比較麻煩,我們要的是班級每個人的成績陣列,由於班級沒有了學生,所以每個人的成績找不到。但是每個人的成績還在資料庫裡存著沒有丟失,我們換一種方法去查詢就好了。我在score_summary實體中加入對應score陣列,這樣可以這樣不用改多對一也可以滿足需求。當我快改完時,學長說還想要在班級管理裡看到原班級的所有學生,這就不得不去改學生與班級關係多對多了。
此時需要將班級和學生一對多關係變為多對多關係。使得原計算機1806班也可以找到所有分班前所在班內的學生。同時需要再對班級和學生陣列設定一對多關係,表示學生當前班級。
/**
* 學生當前所在班級
*/
@ManyToOne
private Klass klass;
/**
* 學生歷史所在班級陣列(包含當前所在班級)
*/
@ManyToMany(mappedBy = "studentList")
@JsonView(KlassListJsonView.class)
private List<Klass> klassList = new ArrayList<>();
然後來修改當前變動出現的問題。首先,由於學生對於班級來說由多對一變為多對多,並且由班級一方負責維護,並且在資料庫中自動建立了klass_student_list中間表。但是我們從班級中找所有學生沒有資料,我們需要先恢復原來班級中所有學生資料。學生中還保留當前班級資訊,我們通過這些資料將同一班級中的學生放到班級的學生陣列裡。這樣中間表就有了相關資料。
List<Klass> klassList = this.klassRepository.findAll();
List<Student> allStudent = this.studentRepository.findAll();
for (Klass klass: klassList) {
List<Student> studentList = new ArrayList<>();
for (Student student: allStudent) {
if (student.getKlass() != null && klass.getId().equals(student.getKlass().getId())) {
studentList.add(student);
}
}
klass.setStudentList(studentList);
}
this.klassRepository.saveAll(klassList);
然後來修改學生更改班級時的程式碼,為了使業務與技術分離思想,我們採用aop形式修改,也減少了對原始碼的改動。思想是在學生變動班級時,在舊班級中將學生刪除,在新班級中將學生新增。
@Before(value = "annotationPointCut(id, student)", argNames = "id, student")
public void before(Long id, Student student) {
Student newStudent = this.studentService.findById(id);
Klass oldKlass = newStudent.getKlass();
Klass newKlass = this.klassService.findById(student.getKlass().getId());
// 如果新班級與舊班級不相等
if (!oldKlass.getId().equals(newKlass.getId())) {
// 刪除舊班級中的這個學生
int i =0;
for (Student student1: oldKlass.getStudentList()) {
if (student1.getId().equals(student.getId())) {
oldKlass.getStudentList().remove(i);
break;
} else {
i++;
}
}
// 在新班級中新增這個學生
newKlass.getStudentList().add(newStudent);
// 儲存
this.klassService.save(oldKlass);
this.klassService.save(newKlass);
}
}
但是重新分班這種情況我不知道是怎麼操作的,我還需要跟學長溝通,我也需要用aop修改這種情況,只需設定新增新班級所有學生就可以了。
可能遇到的問題
我在初始化班級內所有學生資料的時候遇到了一個問題,更新完後中間表沒有任何資料,然後我打斷點看問題,發現在多對多查詢班級時並不會將班級裡所有學生查出來,這是hibernate的懶查詢機制。
解決辦法是在@ManyToMany上關閉懶查詢
@ManyToMany(fetch = FetchType.EAGER)
private List<Student> studentList = new ArrayList<>();