一对一关联包括两种类型:
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
*/
}