《Hibernate学习笔记六》一对一关联关系详解
2016-05-02 21:09
337 查看
《Hibernate学习笔记六》一对一关联关系详解
从今天开始,就要开始学习关联关系了,其中关联关系,分为如下几种:1、一对一关联关系
2、一对多关联关系
3、多对一关联 关系
4、多对多关联关系
总的来说,虽然有如上几种关联方式,但是我们可以理解它只是1中关联方式,就 多对多关联,这是因为其他的关联方式都可以理解为此关联方式的一种特殊方式。
其中,上面提到的关联关系,都存在单向和双向的关联关系。
这篇博文主要介绍下一对一关联关系。
一对一外键关联关系包括:
1、一对一单向外键关联关系的Annotation实现
2、一对一单向外键关联关系的xml实现
3、一对一双向外键关联关系的Annotation实现
4、一对一双向外键关联关系的xml实现
与外键相对应的还有主键关联。
一对一关联
我们生活中有很多一对一关联的例子,例如:”一夫一妻制”就是一对一的关联关系。一个学生有一个身份证也是一个一对一的关联关系。一对一单向外键关联关系Annotation实现
一对一关联使用注解@OneToOne来进行修饰。下面就以:”一夫一妻制”这个例子来进行分析。
Wife实体类
@Entity public class Wife { private int id; private String name; @Id 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; } }
Husband实体类
Huaband实体类中有一个Wife类的引用wife,并在getWife方法上添加了注解@OneToOne,如果我们想指定外键的名字,则通过注解@JoinColumn(name=”wifeId”)来指定,其中wifeId就是我们这个例子中指定的名字。
Husband实体类的具体代码如下:
@Entity public class Husband { private int id; private String name; private Wife wife; @Id @GeneratedValue public int getId() { return id; } @OneToOne @JoinColumn(name="wifeId") //指定外键的名字为wifeId public Wife getWife() { return wife; } public void setWife(Wife wife) { this.wife = wife; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
hibernate.cfg.xml文件内容不再贴出,与前几篇博文的内容类似。
测试代码如下:
public class TeacherTest { @Test public void testSchema(){ ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build(); Metadata metadata = new MetadataSources(serviceRegistry).buildMetadata(); SchemaExport schemaExport = new SchemaExport(); schemaExport.create(EnumSet.of(TargetType.DATABASE), metadata); } }
SchemaExport类主要用于将SQL语句输出到数据库中。
在控制台我们会看到如下的主要输出信息,其中包括两条建表语句,一条插入外键的语句。
以上,这样我们就通过Annotation建立了Husband和Wife一对一单向外键关联关系。
一对一单向外键关联关系XXX.hbm.xml的实现
现在换一个例子,以一个学生有一个身份证这样一个一对一的关联关系来举例分析。Student类
package com.hibernate.model; public class Student { private int id; private String name; // id 、num、 student的getter和setter方法省略 }
IdCard类
public class IdCard { private int id; private String num; private Student student; // id 、num、 student的getter和setter方法省略 }
IdCard.hbm.xml文件内容如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.model"> <class name="IdCard" table="idcard" > <id name="id" column="id"> <generator class="native"/> </id> <property name="num" column="num"/> <!-- 一对一的关联在xml文件中用many-to-one 和unique="true"联合来进行限制 --> <many-to-one name="student" column="studentId" unique="true"></many-to-one> </class> </hibernate-mapping>
上面的代码中:一对一的关联关系在如下的代码中指定:
<many-to-one name="student" column="studentId" unique="true"></many-to-one>
Student.hbm.xml文件内容如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.model"> <class name="Student" table="student" > <id name="id" column="id"> <generator class="native"/> </id> <property name="name" column="name"/> </class> </hibernate-mapping>
这样我们就将Student和IdCard通过外键建立了一对一的关联。
测试文件与第一个例子的测试文件一样,这里不再贴出。
一对一双向外键关联Annotation实现
Student类类中有一个Wife的引用wife。
@Entity public class Husband { private int id; private String name; private Wife wife; @Id @GeneratedValue public int getId() { return id; } @OneToOne @JoinColumn(name="wifeId") //指定外键的名字为wifeId public Wife getWife() { return wife; } //name属性的get方法和所有属性的set方法均省略。 }
Wife实体类
@Entity public class Wife { private int id; private String name; private Husband husband; @OneToOne(mappedBy="wife") //这里的意思为:外键的关联是在Husband的wife对象上面来做,即Husband是主导 public Husband getHusband() { return husband; } public void setHusband(Husband husband) { this.husband = husband; } @Id public int getId() { return id; } //name属性的get方法和所有属性的set方法均省略。 }
Wife类中也有一个Husband类的引用,并且需要在getHusband()方法前用@OneToOne(mappedBy=”wife”)进行注解。如果只用@OneToOne而不使用参数的注解,则会为表Husband和Wife都会建立一个外键的关联,有冗余。
最好的方法:凡是双向关联中,必须要设置@OneToOne(mappedBy=”XXX”)。
一对一双向外键关联XXX.hbm.xml文件实现
即Student类和IdCard类中均有对方的一个引用,且在IdCard.hbm.xml文件中的内容与一对一的内容不变,如下:<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.model"> <class name="IdCard" table="idcard" > <id name="id" column="id"> <generator class="native"/> </id> <property name="num" column="num"/> <!-- 一对一的关联在xml文件中用many-to-one 和unique="true"联合来进行限制 --> <many-to-one name="student" column="studentId" unique="true"></many-to-one> </class> </hibernate-mapping>
而在Student.hbm.xml文件中的内容,有一点变化,
加上了
<one-to-one name="idCard" class="IdCard" property-ref="student"/>
完整内容如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.model"> <class name="Student" table="student" > <id name="id" column="id"> <generator class="native"/> </id> <property name="name" column="name"/> <!--property-ref的参数是本类所关联的类IdCard类中的Student的引用 --> <one-to-one name="idCard" class="IdCard" property-ref="student"/> </class> </hibernate-mapping>
注意:在数据库中,单向和双向是没有区别的,但是,在实体类中的对应关系是有区别的。
一对一主键关联
在外键关联中,例如,会在Husband表中生成一个wifeId的字段作为外键,而主键关联则不会生成其它任意的字段。一对一单向主键关联Annotation实现
用如下的注解来实现:
@PrimaryKeyJoinColumn //用此注解表示主键关联
@Entity public class Husband { private int id; private String name; private Wife wife; @Id @GeneratedValue public int getId() { return id; } @OneToOne //@JoinColumn(name="wifeId") //指定外键的名字为wifeId @PrimaryKeyJoinColumn //用此注解表示主键关联 public Wife getWife() { return wife; } public void setWife(Wife wife) { this.wife = wife; } //一些属性的getter/setter方法 省略 }
一对一单向主键关联xml文件实现
在文档中,给出的方法截图如下:
将上述方法应用到我们的Student类和IdCard类中,如下:
Student类
public class Student { private int id; private String name; //...get、set方法 }
IdCard类
public class IdCard { private int id; private String num; private Student student; //...get、set方法 }
IdCard.hbm.xml文件内容如下:
注意:此时的id生成策略。
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.model"> <class name="IdCard" table="idcard" > <id name="id" column="id"> <generator class="foreign"> <param name="property">student</param> </generator> </id> <property name="num" column="num"/> <!-- --> <one-to-one name="student" class="Student" constrained="true"></one-to-one> </class> </hibernate-mapping>
Student.hbm.xml文件内容如下
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.model"> <class name="Student" table="student" > <id name="id" column="id"> <generator class="native"/> </id> <property name="name" column="name"/> </class> </hibernate-mapping>
测试结果如下:
关于主键关联这里就不再进行过多的介绍,这是由于在实际项目中,一对一关联关系并不太多,即使出现,我们一般也是采用一对一的外键进行关联。
小结
由于使用Annotation比使用xml进行关联关系更容易理解和实现。因此,建议使用。相关文章推荐
- 双向队列
- python 正则学习
- POJ 2947 高斯消元法解同余方程组
- web.xml中关于Servlet、Filter、Listener的配置 顺序问题
- HDU 2040 亲和数(约数模拟)
- Ancient Berland Circus
- js实现的键盘开启大写锁定提示和密码显示与隐藏的效果
- puppet安装和配置
- 图文详解win10/8.1/7系统cmd命令提示符出现“不是内部或外部命令,也不是可运行的程序或批处理文件”
- CentOS7安装iptables防火墙
- [Hash 倍增Floyd] BZOJ 2085 [Poi2010]Hamsters
- 设计模式--单例模式
- 重构:Replace Temp with Query
- Linux下设置xhost方法
- Android:采用SurfaceView设置无声视频
- Pull解析
- 线程同步(一)—— 互斥锁
- [倍增Floyd] BZOJ 1706 [usaco2007 Nov]relays 奶牛接力跑
- HttpServletRequest常用获取URL的方法
- ODEX