Hibernate實體關係對映:單向主鍵一對一關聯
阿新 • • 發佈:2019-02-07
主鍵單向一對一關聯:
1、被控方的主鍵參照主控方的主鍵來生成
2、對應資料庫表關係為被控方的主鍵同時參照引用主控方的主鍵
3、儲存被控方物件,需要先儲存主控方(不然怎麼從native產生主鍵值,被控方更是獲取不到了)
主控方People
People的hbm.xml檔案:只是普通的對映檔案public class People implements java.io.Serializable { // Fields private long id; private String name; private long age; private String sex; // Constructors /** default constructor */ public People() { } // Property accessors public long getId() { return this.id; } public void setId(long id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public long getAge() { return this.age; } public void setAge(long age) { this.age = age; } public String getSex() { return this.sex; } public void setSex(String sex) { this.sex = sex; } }
<hibernate-mapping> <class name="com.sjr.bean.People" table="J_PEOPLE" schema="SXBBKF"> <id name="id" type="long"> <column name="ID" precision="10" scale="0" /> <generator class="native"></generator> </id> <property name="name" type="string"> <column name="NAME" length="20" /> </property> <property name="age" type="long"> <column name="AGE" precision="10" scale="0" /> </property> <property name="sex" type="string"> <column name="SEX" length="2" /> </property> </class> </hibernate-mapping>
從控方IdCard的實體類:
public class IdCard implements java.io.Serializable { // Fields private long id; private People people; <span style="color:#ff0000;">//這裡加上主控方People型別的屬性</span> private String numcode; // Constructors /** default constructor */ public IdCard() { } // Property accessors public long getId() { return this.id; } public void setId(long id) { this.id = id; } public People getPeople() { return this.people; } public void setPeople(People people) { this.people = people; } public String getNumcode() { return this.numcode; } public void setNumcode(String numcode) { this.numcode = numcode; }
IdCard的hbm.xml檔案:負責維護關係
<hibernate-mapping>
<class name="com.sjr.bean.IdCard" table="J_IDCARD" schema="SXBBKF">
<id name="id" type="long">
<column name="ID" precision="10" scale="0" />
<generator class="foreign"> <!--<span style="color:#ff0000;">從控方的主鍵生成策略是 foreign 的方式,這裡的param屬性是它自己對應的屬性名</span>-->
<param name="property">people</param>
</generator>
</id>
<property name="numcode" type="string">
<column name="NUMCODE" length="20" />
</property>
<one-to-one name="people" class="com.sjr.bean.People" constrained="true"></one-to-one> </span>
<span style="font-size:14px;"><span style="white-space:pre"> </span><!--<span style="color:#ff0000;">這裡需要one-to-one進行對映,後面的constrained 後面詳解,主要影響save、delete的先後順序而已,詳情看這裡</span>-->
</class>
</hibernate-mapping>
二、測試增刪改查
(1)查詢
//從控方idcard查詢操作
public void testidcard(){
Session session=null;
try{
session=HibernateUtil.getSession();
IdCard idcard=(IdCard)session.get(IdCard.class, new Long("48"));
</pre><pre name="code" class="java"> //獲取IdCard中Id是48的物件,並進而通過一對一的對映關係獲取其對應的people的值
System.out.println(idcard.getId()+" "+idcard.getNumcode());
System.out.println(idcard.getPeople().getId()+" "+idcard.getPeople().getName()+" "+idcard.getPeople().getAge());
}catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
輸出效果:
Hibernate: select idcard0_.ID as ID0_0_, idcard0_.NUMCODE as NUMCODE0_0_ from SXBBKF.J_IDCARD idcard0_ where idcard0_.ID=?
48 3203203201
Hibernate: select people0_.ID as ID1_0_, people0_.NAME as NAME1_0_, people0_.AGE as AGE1_0_, people0_.SEX as SEX1_0_ from SXBBKF.J_PEOPLE people0_ where people0_.ID=?
48 張三 20
注:如果constrained=true,hibernate即會延遲載入sql,只把主表的查出來,等有用到關聯表的再發sql取。
發放
(2)新增
public void testSaveIdCard(){
Session session=null;
try{
session=HibernateUtil.getSession();
session.getTransaction().begin();
People people=new People();
people.setName("張三");
people.setAge(20);
people.setSex("M"); //主控方的物件
//session.save(people);
IdCard idcard=new IdCard();
idcard.setNumcode("3203203201");
idcard.setPeople(people);
session.save(idcard); //constrained為true,則在插入從控方物件前,需要建立一個主控方People的物件,並set給從控方的IdCard物件;儲存時只需要儲存從控方的物件就行,一次儲存2個物件。
session.getTransaction().commit();
}catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
執行結果:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into SXBBKF.J_PEOPLE (NAME, AGE, SEX, ID) values (?, ?, ?, ?)
Hibernate: insert into SXBBKF.J_IDCARD (NUMCODE, ID) values (?, ?)
(3)刪除
①刪從控方
//刪除 從控方 idcard
public void testRemoveIdCard(){
Session session=null;
try{
session=HibernateUtil.getSession();
session.getTransaction().begin();
/*People people=new People();
people.setName("張三");
people.setAge(20);
people.setSex("M");*/
//session.save(people);
IdCard idcard=(IdCard)session.get(IdCard.class, new Long("48"));
session.delete(idcard);
session.getTransaction().commit();
}catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
執行結果:
Hibernate: select idcard0_.ID as ID0_0_, idcard0_.NUMCODE as NUMCODE0_0_ from SXBBKF.J_IDCARD idcard0_ where idcard0_.ID=?
Hibernate: delete from SXBBKF.J_IDCARD where ID=?
顯然,它只刪除了從控方的物件,並沒有自動關聯刪除主控方的物件
②刪主控方
//刪除 主控方 people
public void testRemovepeople(){
Session session=null;
try{
session=HibernateUtil.getSession();
session.getTransaction().begin();
People people=(People)session.get(People.class, new Long("49"));
session.delete(people);
session.getTransaction().commit();
}catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
執行結果:
Hibernate: select people0_.ID as ID1_0_, people0_.NAME as NAME1_0_, people0_.AGE as AGE1_0_, people0_.SEX as SEX1_0_ from SXBBKF.J_PEOPLE people0_ where people0_.ID=?
Hibernate: delete from SXBBKF.J_PEOPLE where ID=?
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
Caused by: java.sql.BatchUpdateException: ORA-02292: 違反完整約束條件 (SXBBKF.FK28F66C40613448E8) - 已找到子記錄
很顯然,直接刪除主控方,被控方沒有了外來鍵約束關係,這是濰坊約束條件的,所以無法這樣刪除
③手動先刪被控方,再刪主控方
public void removeAll(){
testRemoveIdCard();
testRemovepeople();
}
就是上面兩個方法呼叫一起意思
執行結果:
Hibernate: select idcard0_.ID as ID0_0_, idcard0_.NUMCODE as NUMCODE0_0_ from SXBBKF.J_IDCARD idcard0_ where idcard0_.ID=?
Hibernate: delete from SXBBKF.J_IDCARD where ID=?
Hibernate: select people0_.ID as ID1_0_, people0_.NAME as NAME1_0_, people0_.AGE as AGE1_0_, people0_.SEX as SEX1_0_ from SXBBKF.J_PEOPLE people0_ where people0_.ID=?
Hibernate: delete from SXBBKF.J_PEOPLE where ID=?
這樣必須四條語句了呀,沒有疑問的
四、修改
//修改 從控方 idcard
public void testModifyIdCard(){
Session session=null;
try{
session=HibernateUtil.getSession();
session.getTransaction().begin();
IdCard idcard=(IdCard)session.get(IdCard.class, new Long("47"));
idcard.setNumcode("3203203201010101");
session.update(idcard); //取出記錄,重新賦值後update一下就行,沒有關聯約束關係
session.getTransaction().commit();
}catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
執行結果:
Hibernate: select idcard0_.ID as ID0_0_, idcard0_.NUMCODE as NUMCODE0_0_ from SXBBKF.J_IDCARD idcard0_ where idcard0_.ID=?
Hibernate: update SXBBKF.J_IDCARD set NUMCODE=? where ID=?
綜上,單向主鍵一對一對映關係:從控方的實體類和hbm檔案需要負責維護關係,主控方不用;constrained屬性會影響save操作和刪除操作:save是先主控後從控,delete是先從控後主控。