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

		 */
	}

 

posted on 2011-08-23 13:35  重阳真人  阅读(410)  评论(0编辑  收藏  举报

导航