記錄一次班級與學生修改為多對多關係的過程

小強Zzz發表於2022-01-03

前言

image.png
這周做的是alice專案中的一個bug,由於重新分班後,原班級沒有學生,對於原班級的某一課程成績分析也就沒有了。
lALPDgfLTvPy0pDNAhzNBG0_1133_540.png
比如說我原來是計算機1806班的(計算機專業一共9個班,分別是計算機1801-計算機1809班),由於大專業分流成小專業,我被分為了軟體181班,如果班級和學生是一對多的關係,此時計算機1806班已經沒有學生了,但是成績分析是對一個班的某一課程安排的成績分析,需要獲取這個班所有學生這個課程安排的成績,導致成績分析不能得到所有學生相關成績。

解決

我一開始認為改實體間關係比較麻煩,我們要的是班級每個人的成績陣列,由於班級沒有了學生,所以每個人的成績找不到。但是每個人的成績還在資料庫裡存著沒有丟失,我們換一種方法去查詢就好了。我在score_summary實體中加入對應score陣列,這樣可以這樣不用改多對一也可以滿足需求。當我快改完時,學長說還想要在班級管理裡看到原班級的所有學生,這就不得不去改學生與班級關係多對多了。
此時需要將班級和學生一對多關係變為多對多關係。使得原計算機1806班也可以找到所有分班前所在班內的學生。同時需要再對班級和學生陣列設定一對多關係,表示學生當前班級。
image.png

/**
 * 學生當前所在班級
 */
@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的懶查詢機制。
lALPDgtYzZlnv2fNAZPNBc8_1487_403.png
解決辦法是在@ManyToMany上關閉懶查詢

@ManyToMany(fetch = FetchType.EAGER)
private List<Student> studentList = new ArrayList<>();

相關文章