Hibernate學習之一對一關聯
一對一關聯包括兩種類型:
1.主鍵關聯
2.惟一外鍵關聯
主鍵關聯:
兩張關聯表通過主鍵形成一對一映射關系
實例:一個公民對應一個身份證
1.主鍵關聯
實體類
TUser .java
/** * 主鍵關聯 * */ public class TUser implements Serializable { private static final long serialVersionUID = -133439792227297972L; private Integer id; private Integer age; private String name; private TPassport passport; .......................... }
TPassport.java
/** * 主鍵關聯 * */ public class TPassport implements Serializable{ private static final long serialVersionUID = -2207892280100301351L; private Integer id; private String serial; private Integer expiry; private TUser user; }
配置文件
Tuser.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<!-- 主鍵關聯 -->
<hibernate-mapping>
<class
name="com.model.TUser"
table="t_user"
dynamic-update="true"
>
<id
name="id"
type="java.lang.Integer"
column="id"
unsaved-value="0"
>
<generator class="native" />
</id>
<property name="name" column="name" type="string"/>
<property name="age" column="age" type="java.lang.Integer"/>
<one-to-one name="passport" class="com.model.TPassport" cascade="all" outer-join="false"/>
</class>
</hibernate-mapping>
Tpassport.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<!-- 主鍵關聯 -->
<hibernate-mapping>
<class
name="com.model.TPassport"
table="t_passport"
dynamic-update="true"
>
<id
name="id"
type="java.lang.Integer"
column="id"
unsaved-value="0"
>
<!-- 由于采用了主鍵關聯方式,那么通過主鍵關聯的兩張表,其關聯記錄的主鍵值必須保持同步。
這也就意味著,我們只需為一張表設定主鍵生成策略,而另一張表的主鍵與之共享相同的主鍵值
通過“foreign”類型的主鍵生成策略與外鍵共享主鍵值
-->
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<property name="serial" column="serial" type="string"/>
<property name="expiry" column="expiry" type="java.lang.Integer"/>
<!-- constrained必須是“true”,以告知hibernate當前表主鍵上存在一個約束:t_passport表引用了t_user表的主鍵 -->
<one-to-one name="user" class="com.model.TUser" constrained="true"/>
</class>
</hibernate-mapping>
測試代碼(部分)
//主鍵關聯 public void testSave() { TUser user = new TUser(); user.setName("zhangsan"); user.setAge(20); TPassport passport = new TPassport(); passport.setExpiry(445555); passport.setSerial("PCN2324"); // 設置相互關聯 passport.setUser(user); user.setPassport(passport); try { Transaction tx = session.beginTransaction(); // 由于TUser類的one-to-one節點被設置為cascade=all,其關聯的passport對象將被級聯保存 session.save(user); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } //主鍵關聯 public void testLoad1() { try { TUser user = (TUser) session.load(TUser.class, 1); System.out.println("user name---->" + user.getName()); System.out.println("passport serial---->" + user.getPassport().getSerial()); } catch (HibernateException e) { e.printStackTrace(); } /** out-join="true" 加載TUser實例時 hibernate通過left outer join將t_user表及其關聯的t_group表同時讀出 * Hibernate: select tuser0_.id as id1_, tuser0_.name as name1_, * tuser0_.age as age1_, tpassport1_.id as id0_, tpassport1_.serial as * serial0_, tpassport1_.expiry as expiry0_ from t_user tuser0_ * left outer join * t_passport tpassport1_ on tuser0_.id=tpassport1_.id where tuser0_.id=? */ } //主鍵關聯 public void testLoad2() { try { TUser user = (TUser) session.load(TUser.class, 1); System.out.println("user name---->" + user.getName()); System.out.println("passport serial---->" + user.getPassport().getSerial()); } catch (HibernateException e) { e.printStackTrace(); } /** one-to-one節點設定為 out-join="false"時,分別讀取 * Hibernate: select tuser0_.id as id0_, tuser0_.name as name0_, tuser0_.age as age0_ from t_user tuser0_ where tuser0_.id=? * Hibernate: select tpassport0_.id as id1_, tpassport0_.serial as serial1_, tpassport0_.expiry as expiry1_, tuser1_.id as id0_, tuser1_.name as name0_, tuser1_.age as age0_ from t_passport tpassport0_ left outer join t_user tuser1_ on tpassport0_.id=tuser1_.id where tpassport0_.id=? */ }
2.惟一外鍵關聯
實體類
TGroup.java
/** * 惟一外鍵關聯實體 */ public class TGroup implements Serializable { private static final long serialVersionUID = 263676571059714064L; private Integer id; private String name; // 不加實現的是單向一對一關系 通過Tuser2對象可以獲得其相對應的Tgroup對象,但不能反過來 // 增加是為了實現雙向一對一關系 可以互相獲得 并且還要在TGroup.cfg.xml中追加one-to-one配置 private TUser2 user; ............................. }
TUser2.java
/** *惟一外鍵關聯實體 */ public class TUser2 implements Serializable{ private static final long serialVersionUID = -1898408468538505300L; private Integer id; private Integer age; private String name; private TGroup group; .................. }
配置文件
TGroup.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<class
name="com.model.TGroup"
table="t_group"
dynamic-update="true"
>
<id
name="id"
type="java.lang.Integer"
column="id"
unsaved-value="0"
>
<generator class="native" />
</id>
<property name="name" column="name" type="string"/>
<one-to-one name="user" class="com.model.TUser2" property-ref="group"/>
</class>
</hibernate-mapping>
Tuser2.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<class
name="com.model.TUser2"
table="t_user2"
dynamic-update="true"
>
<id
name="id"
type="java.lang.Integer"
column="id"
unsaved-value="0"
>
<generator class="native" />
</id>
<property name="name" column="name" type="string"/>
<property name="age" column="age" type="java.lang.Integer"/>
<!-- 惟一外鍵關聯的一對一關系只是多對一關系的一個特例而已 -->
<many-to-one name="group" class="com.model.TGroup" column="group_id" unique="true"/>
</class>
</hibernate-mapping>
測試代碼(部分)
public void testSave2(){ TGroup group=new TGroup(); group.setName("group-one"); TUser2 user=new TUser2(); user.setName("lisi"); user.setAge(20); user.setGroup(group); try { Transaction tx=session.beginTransaction(); session.save(user); session.save(group); //必須保存 但先后順序不要求 tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } //單向 user---->group public void testLoad3(){ try { TUser2 user=(TUser2) session.load(TUser2.class, 1); System.out.println("group name--->"+user.getGroup().getName()); } catch (HibernateException e) { e.printStackTrace(); } } //雙向 group-->user public void testLoad4(){ /** * 在TGroup.cfg.xml中不添加one-to-one配置時,查不到user信息 * Hibernate: select tgroup0_.id as id0_, tgroup0_.name as name0_ from t_group tgroup0_ where tgroup0_.id=? Group name---->group-one */ try { TGroup group=(TGroup) session.load(TGroup.class, 1); System.out.println("Group name---->"+group.getName()); System.out.println("group user---->"+group.getUser().getName()); } catch (HibernateException e) { e.printStackTrace(); } /** 添加配置后 * Hibernate: select tgroup0_.id as id1_, tgroup0_.name as name1_, tuser21_.id as id0_, tuser21_.name as name0_, tuser21_.age as age0_, tuser21_.group_id as group_id0_ from t_group tgroup0_ left outer join t_user2 tuser21_ on tgroup0_.id=tuser21_.group_id where tgroup0_.id=? Hibernate: select tuser20_.id as id1_, tuser20_.name as name1_, tuser20_.age as age1_, tuser20_.group_id as group_id1_, tgroup1_.id as id0_, tgroup1_.name as name0_ from t_user2 tuser20_ left outer join t_group tgroup1_ on tuser20_.group_id=tgroup1_.id where tuser20_.group_id=? Group name---->group-one group user---->lisi */ }