Teacher(1) — Class(1) 雙向一對一,雙方表均有外鍵列 class_id、teacher_id。
雞生蛋蛋生雞:插 Teacher 需 Class ID,插 Class 需 Teacher ID。
| 方案 | 步驟 | 優缺點 |
|---|---|---|
| 雙向外鍵 + 事務 | 1. 插 Teacher (class_id=null) 獲取 ID 2. 插 Class (teacher_id=TeacherID) 獲取 ID 3. Update Teacher SET class_id=ClassID 同一事務提交 | 最直觀,需數據庫支持延遲約束檢查或暫時允許 NULL |
| 單向外鍵 (推薦) | 只在一方保留外鍵 (如 Class.teacher_id),另一方通過關聯查詢獲取 | 消除循環依賴,符合數據庫範式,查詢時 JOIN 即可 |
| 共享主鍵 | Teacher.id = Class.id,同一主鍵值 | 插入順序無關,但業務語義綁定較緊 |
<insert id="insertTeacher" useGeneratedKeys="true" keyProperty="id">
INSERT INTO teacher (name) VALUES (#{name})
</insert>
<insert id="insertClass" useGeneratedKeys="true" keyProperty="id">
INSERT INTO class (name, teacher_id) VALUES (#{name}, #{teacherId})
</insert>
<update id="updateTeacherClassId">
UPDATE teacher SET class_id = #{classId} WHERE id = #{teacherId}
</update>
@Transactional
public void addPair(Teacher t, Class c) {
teacherMapper.insertTeacher(t); // t.id 回填
c.setTeacherId(t.getId());
classMapper.insertClass(c); // c.id 回填
teacherMapper.updateTeacherClassId(t.getId(), c.getId());
}
**優先採用單向外鍵**,簡化插入邏輯;若業務強制雙向,則在事務中「插主→插從→更新主」三步走。