Hibernate多表關係配置
- 2019 年 10 月 4 日
- 筆記
Hibernate多表關係配置
1.表的關係
2.一對多配置
3.級聯操作
4.多對多配置
5.多對多操作
1
表的關係
表之間的關係
一對多(一個部門有多個員工,一個員工只能屬於某一個部門)
多對多(一個老師教多個學生,一個學生可以被多個老師教)
一對一(一個公司只能對應一個註冊地址)
表之間關係建表原則
一對多(在多的一方創建一個外鍵,指向一的一方的主鍵)
多對多(創建一個中間表,中間表至少有兩個欄位,分別作為外鍵指向多對多雙方的主鍵)
一對一(唯一外鍵對應或主鍵對應)
2
一對多配置
1.建表(班級、學生)
class_id | class_name | numbers |
|---|
stu_id | stu_name | stu_age | class_id |
|---|
2.建立ORM
domain類
@Getter@Setter public class Classes { private Integer class_id; private String class_name; private Integer class_student; //一個班級包含多個學生 private Set<Student> students = new HashSet<>(); }@Setter@Getter public class Student { private Integer stu_id; private String stu_name; private Integer stu_age; //一個學生屬於一個班級 private Classes stu_class; }映射文件
映射文件中普通欄位段的配置不用寫上外鍵,在一的一方配置文件寫上set標籤name屬性為關聯屬性名,裡面還有key標籤有column屬性關係中的外鍵即另一個表的外鍵欄位名,還有一個標籤one-to-many寫上另一表的domain類全路徑。在多的一方只有一個many-to-one標籤裡面name屬性也是關聯屬性名,class屬性關係表它的domain地址,還有一個column外鍵
<hibernate-mapping> <class name="com.hao.domain.Classes" table="classes"> <id name="class_id" > <generator class="identity"/> </id> <property name="class_name"/> <set name="students"> <key column="class_id"></key> <one-to-many class="com.hao.domain.Student"></one-to-many> </set> </class> </hibernate-mapping>
<hibernate-mapping> <class name="com.hao.domain.Student" table="student"> <id name="stu_id"> <generator class="identity"/> </id> <property name="stu_name" /> <property name="stu_age" /> <many-to-one name="stu_class" class="com.hao.domain.Classes" column="class_id" lazy="false"></many-to-one> </class> </hibernate-mapping>
3.添加核心配置文件
<mapping resource="com/hao/domain/Student.hbm.xml"/> <mapping resource="com/hao/domain/Classes.hbm.xml"/>
4.編寫測試類
public void saveTest() { Session session = HibernateUtil.openSession(); Transaction tra = session.beginTransaction(); //創建三個班級 Classes c1 = new Classes(); Classes c2 = new Classes(); Classes c3 = new Classes(); c1.setClass_name("c1"); c2.setClass_name("c2"); c3.setClass_name("c3"); //創建三個學生 Student s1 = new Student(); Student s2 = new Student(); Student s3 = new Student(); s1.setStu_name("張三"); s2.setStu_name("李四"); s3.setStu_name("王五"); //班級1添加兩個學生,班級2添加一個學生 c1.getStudents().add(s1); c1.getStudents().add(s2); c2.getStudents().add(s3); //保存全部 session.save(s1); session.save(s2); session.save(s3); session.save(c1); session.save(c2); session.save(c3); tra.commit(); }結果
class_id | class-name | numbers |
|---|---|---|
1 | c1 | null |
2 | c2 | null |
3 | c3 | null |
stu_id | stu_name | stu_age | class_id |
|---|---|---|---|
1 | s1 | null | 1 |
2 | s2 | null | 1 |
3 | s3 | null | 2 |
默認是先保存各自的內容,再建立連接(添上外鍵),刪除也是先去掉外鍵再刪除。接下來通過級聯操作實現關聯關係表同步更新
3
級聯操作
按照上面的操作保存3個班級3個學生,共六條保存
理論上只保存一邊是可行的。
比如只保存班級c1、c2、c3,它們添加了s1、s2、s3。
所以添加班級也會在學生表中添加對應的記錄。
但是實際上會報錯——瞬時對象異常
這是因為保存的對象關聯了處於瞬時態的對象
我們可以在配置文件中去開啟級聯操作
在哪個配置文件去開啟,就在它對應的domain保存時才有級聯
在Classes的映射文件去添加cascade,保存classes時就會級聯保存不用再單獨去保存student,關聯資訊本來在classes就有
<set name="students" cascade="save-update"> <key column="class_id" ></key> <one-to-many class="com.hao.domain.Student" ></one-to-many> </set>
還可以寫在Student的映射文件,這樣保存student就會同時保存關聯的classes資訊
<many-to-one cascade="save-update" name="stu_class" class="com.hao.domain.Classes" column="class_id" lazy="false" ></many-to-one>
在更新時也會有級聯操作,當classes移除一個學生,那麼student表會變
還有刪除,當刪除一個班級,那麼student表中屬於這個班的student也會全刪掉
cascade="delete"
4
多對多配置
配置和一對多一樣,只是set標籤中多一個table屬性值為中間關係表的表名
建表
course_id | course_name |
|---|
stu_id | stu_name | stu_age | class_id |
|---|
stu_id | course_id |
|---|
建立ORM
domain類
@Setter@Getter public class Student { private Integer stu_id; private String stu_name; private Integer stu_age; //一個學生有多門課程 private set<Course> courses; }@Setter@Getter public class Course { private Integer Course_id; private String Course_name; //一個課程有眾多學生學習 private set<Student> students; }映射文件
<set name="courses" table="c-s" cascade="save-update,delete"> <key column="stu_id"></key> <many-to-many class="com.hao.domain.Course" column="course_id"></many-to-many> </set>
<set name="students" table="c-s"> <key column="course_id"></key> <many-to-many class="com.hao.domain.Student" column="stu_id"></many-to-many> </set>
最後再在核心配置文件載入上映射文件
<mapping resource="com/hao/domain/Course.hbm.xml"/>
編寫測試
@Test public void manytomany(){ Course c1 = new Course(); Course c2 = new Course(); Course c3 = new Course(); c1.setCourse_name("語文"); c2.setCourse_name("數學"); c3.setCourse_name("英語"); Student s1 = new Student(); Student s2= new Student(); Student s3 = new Student(); s1.setStu_name("張三"); s2.setStu_name("李四"); s3.setStu_name("王五"); c1.getStudents().add(s1); c1.getStudents().add(s2); c1.getStudents().add(s3); c2.getStudents().add(s1); c3.getStudents().add(s2); c3.getStudents().add(s3); Session session = HibernateUtil.openSession(); Transaction tra = session.beginTransaction(); session.save(c1); session.save(c2); session.save(c3); tra.commit(); }


5
多對多操作
對多對的操作雙方的關係都在中間表上,都在各自得關聯集合中。所以它們得操作就是操作集合
給上面王五添加數學課
@Test public void manytomany(){ Session session = HibernateUtil.openSession(); Transaction tra = session.beginTransaction(); //獲取王五 Student stu = session.get(Student.class,1); //獲取數學課 Course course = session.get(Course.class,2) //修改集合 stu.getCourses().add(course); tra.commit(); }
其他也是一樣
給王五刪除數學課
@Test public void manytomany(){ Session session = HibernateUtil.openSession(); Transaction tra = session.beginTransaction(); //獲取王五 Student stu = session.get(Student.class,1); //獲取數學課 Course course = session.get(Course.class,2) //修改集合 stu.getCourses().remove(course); tra.commit(); }給王五把英語課改為數學課(其實就是前面的刪除和添加)
@Test public void manytomany(){ Session session = HibernateUtil.openSession(); Transaction tra = session.beginTransaction(); //獲取王五 Student stu = session.get(Student.class,1); //獲取英語課 Course course1 = session.get(Course.class,3); //獲取數學課 Course course2 = session.get(Course.class,2); //修改集合 stu.getCourses().remove(course1); stu.getCourses().add(course2); tra.commit(); }特別注意:事務提交、建表引擎(坑)