`
oham_一1一
  • 浏览: 51605 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Hibernate使用——一对一关联示例

阅读更多

一对一关联

一对一关联包括如下的两种类型:

  1. 主键关联

  2. 唯一外键关联

 

主键关联 

       一对一的主键关联形式,即两张关联表通过主键形成一对一映射关系。

       下面是一个例子,oham 阵型与lulu阵型配对进行精神单挑,要求两组阵型人数相同,一对一PK:

 

TOham.java

 

package learnHibernate.bean;

import java.io.Serializable;

public class TOham implements Serializable {
	private static final long serialVersionUID = -3474820872619575460L;
	
	private int id;
	private String name;
	private int groupId;
	private String meditation;
	
	private TLulu lu;

	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;
	}
	public int getGroupId() {
		return groupId;
	}
	public void setGroupId(int groupId) {
		this.groupId = groupId;
	}
	public TLulu getLu() {
		return lu;
	}
	public void setLu(TLulu lu) {
		this.lu = lu;
	}
	public String getMeditation() {
		return meditation;
	}
	public void setMeditation(String meditation) {
		this.meditation = meditation;
	}
}

 

TLulu.java

package learnHibernate.bean;

import java.io.Serializable;

public class TLulu implements Serializable {
	private static final long serialVersionUID = -252962688967803016L;
	
	private int id ;
	private String name;
	private String sixthSense;
	
	private TOham oh;

	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;
	}

	public TOham getOh() {
		return oh;
	}

	public void setOh(TOham oh) {
		this.oh = oh;
	}

	public String getSixthSense() {
		return sixthSense;
	}

	public void setSixthSense(String sixthSense) {
		this.sixthSense = sixthSense;
	}
}

 

 TOham.hbm.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  
<hibernate-mapping package="learnHibernate.bean">
	<class name="TOham" table="t_oham">
		<id name="id" column="id" type="java.lang.Integer">
			<generator class="native"/>
		</id>
		
		<property name="name" 
				  column="name" 
				  type="java.lang.String" />
				  
		<property name="meditation" 
				  column="meditation" 
				  type="java.lang.String" />
				  
		<property name="groupId" 
				  column="group_id" 
				  type="java.lang.Integer" />
				  
				  
		<!-- 通过one-to-one节点,将Toham类与TLulu类相关联 -->		  
		<!-- cascade属性,当主控方执行操作的时候,关联对象是否执行同一操作,
		     如主控对象save-update-delete的时候,是否也同时对关联对象做相同动作,
		     此处为“all”,表示对关联类做同样的动作 -->		  
		<one-to-one name="lu"
					class="TLulu"
					cascade="all"
					outer-join="true">
		</one-to-one>

	</class>
</hibernate-mapping>

 

 

TLulu.hbm.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  
<hibernate-mapping package="learnHibernate.bean">
	<class name="TLulu" table="t_lulu">
		<id name="id" column="id" type="java.lang.Integer">
		
			<!-- t_oham与t_lulu采用了主键关联方式,所以关联的记录主键值必须保持同步 -->
			<!-- 所以只需为一张表设定主键生成器,而另一张表的主键与之共享相同的主键值 -->
			<!-- 此处用foreign类型的主键生成器,表示t_lulu的主键id同时为外键,
			             通过property:oh的TOham类表明关联的映射表为t_oham  -->
			<generator class="foreign">
				<param name="property">oh</param>
			</generator>
		</id>
		<!-- constrained为true,表明表t_oham的主键,被当前表t_lulu的外键关联着 -->
		<one-to-one name="oh"
					class="TOham" 
					constrained="true"/>
		
		<property name="name" 
				  column="name" 
				  type="java.lang.String" />
				  
		<property name="sixthSense" 
				  column="sixthsense" 
				  type="java.lang.String" />
				  
	</class>
</hibernate-mapping>

 

 

执行代码:

package learnHibernate;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;

import learnHibernate.bean.TLulu;
import learnHibernate.bean.TOham;
import learnHibernate.util.HibernateLocalUtil;

public class TestCase7 {

	@Test
	public void saveOrUpdateOhamlulu() {
		TOham oh = new TOham();
		oh.setName("Oham");
		oh.setMeditation("foresee");
		
		TLulu lu = new TLulu();
		lu.setName("Lulu");
		lu.setSixthSense("Perspective");
		
		//互相设置关联,否则会抛
		//org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
		oh.setLu(lu);
		lu.setOh(oh);
		
		SessionFactory factory = HibernateLocalUtil.getSessionFactory();
		Session session = factory.openSession();
		Transaction tx = session.beginTransaction();
		
		//由于TOham映射文件中的one-to-one节点设置了cascade="all"
		//此处会被联级保存,若设置为"none",则只保存TOham
		session.save(oh);
		
		tx.commit();
		session.close();
		
	}
	
	//@Test
	public void getOhamlulu() {
		SessionFactory factory = HibernateLocalUtil.getSessionFactory();
		Session session = factory.openSession();
		
		TOham oh = (TOham)session.load(TOham.class, new Integer(9));
		
		//TLulu lu = (TLulu)session.load(TLulu.class, new Integer(9));
		
		//System.out.println(oh.getName());
		//System.out.println(lu.getName());
		session.close();
	}
	
	
}

 

  后台输出sql:

Hibernate: 
    insert 
    into
        t_oham
        (name, meditation, group_id) 
    values
        (?, ?, ?)
Hibernate: 
    insert 
    into
        t_lulu
        (name, sixthsense, id) 
    values
        (?, ?, ?)

 

然后执行查询代码:

TOham oh = (TOham)session.load(TOham.class, new Integer(9));
		//因为TOham默认为延迟加载,调用对象时才会执行查询数据库
		System.out.println(oh.getName());

 后台输出sql:

Hibernate: 
    select
        toham0_.id as id0_1_,
        toham0_.name as name0_1_,
        toham0_.meditation as meditation0_1_,
        toham0_.group_id as group4_0_1_,
        tlulu1_.id as id1_0_,
        tlulu1_.name as name1_0_,
        tlulu1_.sixthsense as sixthsense1_0_ 
    from
        t_oham toham0_ 
    left outer join
        t_lulu tlulu1_ 
            on toham0_.id=tlulu1_.id 
    where
        toham0_.id=?

 

注意:若将TOham.hbm.xml的outer-join设置为“false”,重新执行查询代码,结果:

 后台输出sql:

Hibernate: 
    select
        toham0_.id as id0_0_,
        toham0_.name as name0_0_,
        toham0_.meditation as meditation0_0_,
        toham0_.group_id as group4_0_0_ 
    from
        t_oham toham0_ 
    where
        toham0_.id=?
Hibernate: 
    select
        tlulu0_.id as id1_0_,
        tlulu0_.name as name1_0_,
        tlulu0_.sixthsense as sixthsense1_0_ 
    from
        t_lulu tlulu0_ 
    where
        tlulu0_.id=?

这时,再把TLulu.hbm.xml的constrained设置为“false”,执行代码,结果:

Hibernate: 
    select
        toham0_.id as id0_0_,
        toham0_.name as name0_0_,
        toham0_.meditation as meditation0_0_,
        toham0_.group_id as group4_0_0_ 
    from
        t_oham toham0_ 
    where
        toham0_.id=?
Hibernate: 
    select
        tlulu0_.id as id1_1_,
        tlulu0_.name as name1_1_,
        tlulu0_.sixthsense as sixthsense1_1_,
        toham1_.id as id0_0_,
        toham1_.name as name0_0_,
        toham1_.meditation as meditation0_0_,
        toham1_.group_id as group4_0_0_ 
    from
        t_lulu tlulu0_ 
    left outer join
        t_oham toham1_ 
            on tlulu0_.id=toham1_.id 
    where
        tlulu0_.id=?

 说实话,在下不太明白constrained的具体作用,只知道当在采用主键关联的方式去做一对一关联时,从表(这里的例子t_lulu)的映射配置里id 的foreign类generator必须与constrained设置为true配对出现。

注意的一点是主从关系,我一般这样理解,持有外键的表是从表,是关联方,而被关联的表是主表,是主控方,被关联方,在hibernate的映射当中主从理清关系很重要,因为涉及级联操作,弄不好会造成逻辑混乱。

 

 

唯一外键关联

顾名思义,通过非主键的唯一外键来做一对一关联,现在举一例子:先前oham与lulu两阵型心灵单挑进行中,可惜两组总体水平相去甚远,现在oham组要求组内每人可以召唤帮托,但为兼顾公平,现在只允许每人召唤一个,并且只能是cancan类型的,还有不能召唤同一人。。。


 TOham.java:

package learnHibernate.bean;

import java.io.Serializable;

public class TOham implements Serializable {
	private static final long serialVersionUID = -3474820872619575460L;
	
	private int id;
	private String name;
	private int groupId;
	private String meditation;
	
	private TLulu lu;
	
	private TCancan can;

	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;
	}
	public int getGroupId() {
		return groupId;
	}
	public void setGroupId(int groupId) {
		this.groupId = groupId;
	}
	public TLulu getLu() {
		return lu;
	}
	public void setLu(TLulu lu) {
		this.lu = lu;
	}
	public String getMeditation() {
		return meditation;
	}
	public void setMeditation(String meditation) {
		this.meditation = meditation;
	}
	public TCancan getCan() {
		return can;
	}
	public void setCan(TCancan can) {
		this.can = can;
	}
}

TCancan.java:

package learnHibernate.bean;

public class TCancan {

	private int id;
	private String name;
	private String think;
	
	private TOham oh;
	
	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;
	}
	public String getThink() {
		return think;
	}
	public void setThink(String think) {
		this.think = think;
	}
	public TOham getOh() {
		return oh;
	}
	public void setOh(TOham oh) {
		this.oh = oh;
	}
}

 

 

 

 TOham.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  
<hibernate-mapping package="learnHibernate.bean">
	<class name="TOham" table="t_oham">
		<id name="id" column="id" type="java.lang.Integer">
			<generator class="native"/>
		</id>
		
		<property name="name" 
				  column="name" 
				  type="java.lang.String" />
				  
		<property name="meditation" 
				  column="meditation" 
				  type="java.lang.String" />
				  
		<property name="groupId" 
				  column="group_id" 
				  type="java.lang.Integer" />
				  
		<one-to-one name="lu"
					class="TLulu"
					cascade="all"
					outer-join="true">
		</one-to-one>
		
		<!-- 外键关联,一般是多对一的,唯一外键关联只是其中一个特例,
		  	  所以此处用了many-to-one,并设置unqiue为true,表明此外键唯一 -->
		<many-to-one name="can" 
		             class="TCancan"
		             column="friend_id"
		             unique="true"/>

	</class>
</hibernate-mapping>

 

TCancan.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  
<hibernate-mapping package="learnHibernate.bean">
	<class name="TCancan" table="t_cancan">
		<id name="id" column="id" type="java.lang.Integer">
			<generator class="native" />
		</id>
		
		<!--<one-to-one name="oh"
					class="TOham"
					property-ref="can" />-->
		
		<property name="name" 
				  column="name" 
				  type="java.lang.String" />
				  
		<property name="think" 
				  column="think" 
				  type="java.lang.String" />
				  
	</class>
</hibernate-mapping>

 

 

执行代码:

TOham oh = (TOham)session.load(TOham.class, new Integer(6));
		System.out.println(oh.getCan().getName());

结果:

Hibernate: 
    select
        toham0_.id as id0_1_,
        toham0_.name as name0_1_,
        toham0_.meditation as meditation0_1_,
        toham0_.group_id as group4_0_1_,
        toham0_.friend_id as friend5_0_1_,
        tlulu1_.id as id1_0_,
        tlulu1_.name as name1_0_,
        tlulu1_.sixthsense as sixthsense1_0_ 
    from
        t_oham toham0_ 
    left outer join
        t_lulu tlulu1_ 
            on toham0_.id=tlulu1_.id 
    where
        toham0_.id=?
Hibernate: 
    select
        tcancan0_.id as id2_0_,
        tcancan0_.name as name2_0_,
        tcancan0_.think as think2_0_ 
    from
        t_cancan tcancan0_ 
    where
        tcancan0_.id=?

 此处要注意的是因为先前的例子我们做了主键一对一关联,所以此处left join了t_lulu表,若是用单纯的唯一外键映射例子做实验,此处的sql可能是left outer join的,可以去试试,因为many-to-one的outer-join默认为true。这是hibernate底层优化的结果。

另外 注意若不调用oh下面的can对象的话hibernate不会去执行查询t_canca的操作。

 

此处在hibernate的映射层面是个单向的关联,也就是说,执行下面代码:

TCancan can = (TCancan)session.load(TCancan.class, new Integer(1));
		System.out.println(can.getOh());

 结果是hibernate只会查询t_cancan表,不会去查t_oham表:

Hibernate: 
    select
        tcancan0_.id as id2_0_,
        tcancan0_.name as name2_0_,
        tcancan0_.think as think2_0_ 
    from
        t_cancan tcancan0_ 
    where
        tcancan0_.id=?

 

 

若我们把TCancan.hbm.xml中的one-to-one节点的注释放开:

<one-to-one name="oh"
					class="TOham"
					property-ref="can" />

 其中property-ref指定为TOham的属性名为can,意思是TOham的can就是关联着本类TCancan的。这样就实现了映射层面的双向关联。

在执行代码:

TCancan can = (TCancan)session.load(TCancan.class, new Integer(1));
		System.out.println(can.getOh());

 结果把t_cancan关联进来了:

Hibernate: 
    select
        tcancan0_.id as id2_2_,
        tcancan0_.name as name2_2_,
        tcancan0_.think as think2_2_,
        toham1_.id as id0_0_,
        toham1_.name as name0_0_,
        toham1_.meditation as meditation0_0_,
        toham1_.group_id as group4_0_0_,
        toham1_.friend_id as friend5_0_0_,
        tlulu2_.id as id1_1_,
        tlulu2_.name as name1_1_,
        tlulu2_.sixthsense as sixthsense1_1_ 
    from
        t_cancan tcancan0_ 
    left outer join
        t_oham toham1_ 
            on tcancan0_.id=toham1_.friend_id 
    left outer join
        t_lulu tlulu2_ 
            on toham1_.id=tlulu2_.id 
    where
        tcancan0_.id=?

 

此处就引申了一个问题,若一个实体的映射关联多了,就不能总让其join来join去了,那么就要考虑如何设置映射配置,使得性能最优化。。。

 

 

  • 大小: 8.7 KB
  • 大小: 7.4 KB
分享到:
评论
1 楼 zilang12 2013-08-16  
Hi bryan, 我来你这溜达一下

相关推荐

    Hibernate使用——入门

    - **一对一**:使用`@OneToOne`注解建立一对一关系。 - **一对多**:`@ManyToOne`和`@OneToMany`注解用于一对多关系,`@OneToMany`通常配合`@JoinColumn`使用。 - **多对多**:`@ManyToMany`处理多对多关系,需要...

    Hibernate总结——课程管理

    本教程将深入探讨如何使用Hibernate来实现一个简单的课程管理系统,涵盖多对多关联映射以及CRUD操作。 ### Hibernate概述 Hibernate是一个开源的ORM框架,它允许开发者使用Java对象来表示数据库中的记录,从而避免...

    Hibernate教程05_关系映射之一对一双向外键关联

    在Hibernate中,一对一关联的配置主要通过注解或XML配置文件完成。对于双向关联,我们需要在两个实体类中分别设置相应的属性和关联注解。 在实体类A中,我们将添加一个类型为B的属性,并使用`@OneToOne`注解来指定...

    Hibernate教程07_关系映射之一对一双向主键关联

    在本教程中,我们将深入探讨Hibernate中的一个关键概念——关系映射,特别是“一对一双向主键关联”。这种关联类型是数据库设计中的常见模式,它允许两个实体类之间通过共享相同的主键来建立关联。在Java应用中,...

    Hibernate ORM - 一对多双向组合关联关系

    这个标题表明我们要讨论的是Hibernate ORM框架中的一种特定的数据关系映射——一对多双向组合关联。在关系型数据库中,一对多关联意味着一个父实体可以与多个子实体相对应,而双向则表示这种关系是相互的,即父实体...

    jpa之使用hibernate示例代码

    6. **关联映射**:JPA允许定义实体之间的关联,如一对一(@OneToOne),一对多(@OneToMany),多对一(@ManyToOne)和多对多(@ManyToMany)。这些关联可以通过属性或集合进行映射。 7. **懒加载和即时加载**:...

    J2EE示例项目——注册

    在IT行业中,J2EE(Java 2 Platform, Enterprise Edition)是一个广泛使用的开源框架,用于构建企业级的分布式应用程序。本示例项目“J2EE示例项目——注册”是针对J2EE平台的一个具体应用,它展示了如何实现用户...

    Hibernate教程10_关系映射之多对一单向关联

    本教程主要聚焦于Hibernate中的一个关键概念——关系映射,特别是多对一单向关联的实现。这种关联类型常出现在数据库设计中,比如一个部门可以有多名员工,但一个员工只属于一个部门。 首先,我们要理解多对一关系...

    hibernate 关联映射(三) one to one(双向)

    总结来说,Hibernate的双向一对一关联映射涉及两个实体类之间的相互引用,需要在每个实体类上使用`@OneToOne`注解,并通过`mappedBy`指定关联的方向。此外,主键共享是通过`@PrimaryKeyJoinColumn`注解实现的。理解...

    Hibernate数据关联映射与继承策略

    1. **一对一关联(One-to-One)**:一个实体对应数据库中的另一张表中的唯一一条记录。这可以通过在主键上添加外键约束或使用单独的关联表来实现。 2. **一对多关联(One-to-Many)**:一个实体可以与数据库表中的...

    Hiberante part 9:一对一关系映射

    在本篇博文中,我们将深入探讨Hibernate框架中的一个重要特性——一对一(One-to-One)关系映射。Hibernate作为Java领域中最流行的ORM(对象关系映射)工具,它允许开发者以面向对象的方式处理数据库操作,简化了...

    hibernate课程源码.

    在Hibernate中,一对一关系允许两个实体之间建立一对一的关联,学习这部分可以理解如何配置和使用这种关联。 4. **006_Hibernate_OneToMany**: 这部分讲解了一对多(OneToMany)关系映射,这是最常见的对象关系映射...

    hibernate多对多关联的问题

    在使用Hibernate框架处理实体间多对多关系时,经常会遇到一个棘手的问题——如何有效地管理中间关联表(如`role_popedom`),特别是在执行删除和更新操作时。本文将基于一个具体的示例场景,深入探讨这一问题,并...

    HIBERNATE doc_document_官方文档_4.3.6_final_2014_8

    - **Hibernate教程**: 包括第一部分——第一个Hibernate应用程序,第二部分——映射关联,第三部分——EventManager Web应用程序。每部分都提供了详细的步骤和代码示例,让开发者能够通过实践来学习Hibernate的使用...

    hibernate.jar

    5. 支持关联映射:一对多、一对一、多对多等各种关联关系的映射。 6. 插件扩展:例如,Hibernate Search允许对数据库进行全文搜索。 六、最佳实践 - 避免在循环中使用Session,以免引发内存泄漏。 - 使用...

    Hibernate5实例程序

    Hibernate支持多种关系映射,如一对一(`@OneToOne`)、一对多(`@OneToMany`)、多对一(`@ManyToOne`)和多对多(`@ManyToMany`)。每种关系映射都有相应的配置方法。 11. **懒加载(Lazy Loading)** 通过`@...

    Hibernate 框架测试版本

    Hibernate 支持多种关系映射,如一对一(@OneToOne)、一对多(@OneToMany)、多对一(@ManyToOne)和多对多(@ManyToMany)。通过这些注解,你可以定义实体之间的关联关系。 10. **实用工具** Hibernate 提供了...

    Hibernate学习

    - **标签**:用于指定一对一关联关系。 - **一对一主键关联映射存储测试**:演示如何存储具有主键关联的一对一关系。 - **一对一主键关联映射加载测试**:演示如何加载具有主键关联的一对一关系的数据。 - **一对一...

    Hibernate开发指南

    - **一对一关联**: - 单向一对一: 一方持有另一方的外键。 - 双向一对一: 双方相互持有对方的引用。 - **一对多关联**: - **单向一对多**: 父对象持有子对象集合的引用。 - **双向一对多**: 子对象反过来也持有...

Global site tag (gtag.js) - Google Analytics