Hibernate中最繞的部分莫過於各類映射了,其實大體上就3種,一對一映射onetoone,一對多映射onetomany,多對一映射manytoone,多對多映射manytomany。一對一映射又有一對一主鍵映射和惟一外鍵映射。java
第一種,一對一主鍵映射,咱們這裏用Person和IdCard舉例,人和身份證是一對一的關係數據庫
其中Idcard的配置以下:session
<class name="com.xiaoming.test.hibernate.personTest.IdCard" table="idcard"> <id name="id" length="4"> <generator class="native"></generator> </id> <property name="cardNo" length="10"></property> <one-to-one name="person" ></one-to-one> </class>
person的配置以下:
學習
<class name="com.xiaoming.test.hibernate.personTest.Person" table="person"> <id name="id" length="4"> <generator class="foreign"> <param name="property">idCard</param> </generator> </id> <property name="name" length="10"></property> <one-to-one name="idCard" constrained="true"></one-to-one> </class>
其中person的主鍵來自idcard,也就是共享idcard的主鍵。constrained="true"的含義,代表當前主鍵上存在一個約束,person的主鍵做爲外鍵參照了idCard, 這裏在進行person對象操做時,要求idCard不 能爲null 測試
IdCard idCard = new IdCard(); idCard.setCardNo("1234567890"); Person person = new Person(); person.setName("張三"); idCard.setPerson(person); session.save(idCard);
這種狀況,person是依賴idcard。可是idcard並無cascade到person,因此這個操做只會保存idcard對象spa
IdCard idCard = new IdCard(); idCard.setCardNo("1234567890"); Person person = new Person(); person.setName("張三"); idCard.setPerson(person); session.save(person);
這種狀況在保存person的時候,person並無綁定idcard,而其id又是依賴idcard的id的,因此這樣執行會報錯。hibernate
IdCard idCard = new IdCard(); idCard.setCardNo("1234567890"); Person person = new Person(); person.setName("張三"); person.setIdCard(idCard); session.save(person);
這種狀況是能夠正常保存idcard和person的code
讀取的代碼以下:orm
Person p=(Person)session.load(Person.class, 1); System.out.println(p); System.out.println(p.getIdCard()); IdCard idCard=(IdCard)session.get(IdCard.class, 1); System.out.println(idCard); System.out.println(idCard.getPerson());
第二種映射狀況是一對一惟一外鍵映射, 一對惟一外鍵關聯映射是採用多對一關聯映射方法來解決一對一的問題,它就是多對一的一個特例。它是基於這樣一種思想:在映射多的一端時採用<many-to-one>標籤,而且用屬性unique=true來限定它是惟一的,這樣就實現了多的一端的多重性爲一。可是,它仍保留多対一的痕跡(好比關係模型中增長一個外鍵字段)。xml
其中idcard的配置以下:
<class name="com.xiaoming.test.hibernate.personTest2.IdCard" table="idcard"> <id name="id" length="4"> <generator class="native"></generator> </id> <property name="cardNo" length="10"></property> <one-to-one name="person" class="com.xiaoming.test.hibernate.personTest2.Person" property-ref="idCard" cascade="save-update" ></one-to-one> </class>
property-ref="idCard"含義,指示加載關聯對象時根據關聯對象對本對象的引用(即根據person的idCard屬性) 測試代碼以下:
person的配置以下:
<class name="com.xiaoming.test.hibernate.personTest2.Person" table="person"> <id name="id" length="4"> <generator class="native"></generator> </id> <property name="name" length="10"></property> <!--many-to-one標籤的含義,是在本表中增長外鍵指向另外一端。 unique="true"含義,是本表的本字段加上惟一性約束. --> <many-to-one name="idCard" class="com.xiaoming.test.hibernate.personTest2.IdCard" unique="true" column="card_id" cascade="save-update"></many-to-one> </class>
many-to-one是在本表中增長外鍵指向另外一端,unique=true的含義表示在本表的本字段加上惟一性約束。
IdCard idCard=new IdCard(); idCard.setCardNo("1234567890"); Person person=new Person(); person.setIdCard(idCard); session.save(person);
這種狀況是ok的,會同事插入person和idcard兩個對象,由於idcard中的onetoone標籤有cacade=save-updatre屬性
IdCard idCard=new IdCard(); idCard.setCardNo("1234567890"); session.save(idCard); Person person=new Person(); person.setName("張三"); person.setIdCard(idCard); session.save(person);
這種寫法也是對的。會同時插入idcard及person屬性
Person person=new Person(); person.setName("奇隆"); IdCard idCard=new IdCard(); idCard.setCardNo("1234567890"); idCard.setPerson(person);
若是在IdCard一端沒有cascade="save-update",顯然這裏會只插入idCard,而不會級聯插入它的person屬性 。若是在IdCard一端有cascade="save-update",則在插入idCard後,會再插入person,可是idCard_id字段會是null,而不會把person的idCard_id更新. 因此像這種狀況,應該在"多"的一端插入並級聯"一"的一端.
讀取操做以下:
Person p=(Person)session.load(Person.class, 2); System.out.println(p); System.out.println(p.getIdCard()); IdCard idCard=(IdCard)session.get(IdCard.class, 5); System.out.println(idCard); System.out.println(idCard.getPerson());
第3中是多對一的映射,咱們這裏用group和user來舉例
Group配置對下:
<class name="com.xiaoming.test.hibernate.userTest.Group" table="group1"> <id name="id" length="4"> <generator class="native"></generator> </id> <property name="name" length="10"></property> </class>
User的配置以下:
<class name="com.xiaoming.test.hibernate.userTest.User" table="user1"> <id name="id" length="4"> <generator class="native"></generator> </id> <property name="name" length="10"></property> <many-to-one name="group" column="group_id" cascade="save-update"></many-to-one> </class>
many-to-one含義,會在多的一端加入一個外鍵指向一的一端,以供加載時使用.外鍵由column屬性指定,默認和實體屬性名相同. cascade操做本對象時級聯操做它的關聯對象
測試方法以下:
Group group = new Group(); group.setName("研發組"); User user=new User(); user.setName("奇隆"); user.setGroup(group); session.save(user);
這種操做是ok的,由於user加了casecade屬性,因此在插入user以前會插入group
Group group=(Group)session.get(Group.class, 2); User user=new User(); user.setName("謝霆鋒"); user.setGroup(group); session.save(user);*/
這種狀況group是已經在數據庫中並加載出來的,因此也能保存成功。
User user = (User) session.get(User.class, 3);// 只是加載了user對象和它所在組的對象group的id屬性,並無加載group對象 System.out.println(user); System.out.println(user.getGroup()); session.save(user); user.setName("鄭伊健"); session.save(user);
第一次save的時候因爲user沒有作update操做,因此不會觸發update操做,第二個save操做因爲user有變更,因此能夠觸發update操做
其實每種案例都差很少,無非就是one和many標籤及其中屬性的配合,另外java代碼中注意調用的順序,就能夠正常操做對應的對象屬性,這一次這幾種映射關係沒有介紹完,下一次再學習manytoone,manytomany及符合主鍵的映射。