(10)hibernate中OneToOne雙向
首先在person類加入idcard:
public class Person { private int id; private String name; private IdCard idcard; public IdCard getIdcard() { return idcard; } public void setIdcard(IdCard idcard) { this.idcard = idcard; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Person.hbm.xml加入one-to-one:
<hibernate-mapping> <class name="model.Person" table="PERSON"> <id name="id" type="int"> <column name="ID" /> <generator class="native" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" /> </property> <one-to-one name="idcard" property-ref="person"></one-to-one> </class> </hibernate-mapping>
注意(1).one-to-one proper-ref=“person”表示由對端(idcard)的person屬性維護關係
test01:
void test3() { Session s=null; try { s=HibernateUtil.getSession(); s.beginTransaction(); IdCard idcard=new IdCard(); idcard.setNumber(1234); s.save(idcard); Person person=new Person(); person.setName("haha"); person.setIdcard(idcard); s.save(person); s.getTransaction().commit(); } catch (Exception e) { // TODO 自動生成的 catch 塊 e.printStackTrace(); s.getTransaction().rollback(); }finally { HibernateUtil.closeSession(s); } }
注意(1).此時新增的資料P_ID為null,因為關係是在idcard的person屬性維護,應該idcard,setPerson而不是person.setIdcard,所以P_ID為null
test02:
void test4() {
Session s=null;
try {
s=HibernateUtil.getSession();
s.beginTransaction();
Person person=new Person();
person.setName("haha");
s.save(person);
IdCard idcard=new IdCard();
idcard.setNumber(1234);
idcard.setPerson(person);
s.save(idcard);
s.getTransaction().commit();
} catch (Exception e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
s.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(s);
}
}
此時即可成功新增P_ID,因為此時關係由idcard的person屬性維護
test03:
void test5() {
Session s=null;
try {
s=HibernateUtil.getSession();
s.beginTransaction();
Person person=s.load(Person.class, 3);
System.out.println(person.getName()+","+person.getIdcard().getNumber());
s.getTransaction().commit();
} catch (Exception e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
s.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(s);
}
}
注意(1).load如果取的是沒有維護關係的這一端,就會將關聯物件取出,自動完成join,就左右一條sql語句
test04:
void test6() {
Session s=null;
try {
s=HibernateUtil.getSession();
s.beginTransaction();
IdCard idcard=s.load(IdCard.class, 4);
System.out.println(idcard.getNumber()+","+idcard.getPerson().getName());
s.getTransaction().commit();
} catch (Exception e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
s.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(s);
}
}
注意(1).此時發3條sql語句,因為取的是維護關係的這一端idcard,一條語句取idcard,一條語句取idcard中person,最後1條語句取idcard中的person裡面的idcard屬性
test05:把person裡面的idcard屬性刪除以及把Person.hbm.xml裡面的one-to-one刪除,再次執行test04,此時發2條sql,一條取idcard,一條取idcard,一條取idcard裡的person,因為此時person裡面沒有idcard屬性,所以不會再去取person裡面的idcard,因此少了一條sql語句
最佳實踐:one-to-one最好不要使用雙向關聯,如果使用了雙向關聯,儘可能在沒有維護關係的一端取資料,hibernate會自動完成join操作,僅僅發一條sql。如果取的是維護關係的一端,會先取idcard,再取idcard裡面的person,由於person裡面還有idcard,所以還會再取,所以總共3條sql語句。