版权声明:本文为博主原创文章,如需转载请标注转载地址。

博客地址:http://www.cnblogs.com/caoyc/p/5602418.html 

一对一关联,可以分为两种。一种是基于外键的关联,另一种是基于主键的关联。如图

一、基于外键的方式

  

  User.java

 package com.proc.one2one;

 public class User {

     private Integer id;
private String name;
private IdCard card;
public User() {
}
public User(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IdCard getCard() {
return card;
}
public void setCard(IdCard card) {
this.card = card;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}

  IdCard.java

 package com.proc.one2one;

 public class IdCard {

     private Integer id;
private String cardNo;
private User user;
public IdCard(String cardNo) {
this.cardNo = cardNo;
}
public IdCard() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "IdCard [id=" + id + ", cardNo=" + cardNo + "]";
} }

  

  User.hbm.xml

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.proc.one2one">
<class name="User" table="t_user">
<id name="id" type="int" column="id" >
<generator class="native"></generator>
</id>
<property name="name" length="20" not-null="true"></property>
<one-to-one name="card" class="IdCard"></one-to-one>
</class>
</hibernate-mapping>

  

  IdCard.hbm.xml

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.proc.one2one">
<class name="IdCard" table="t_idcard">
<id name="id" type="int" column="id" >
<generator class="native"></generator>
</id>
<property name="cardNo" type="string" column="cardNo" length="20" not-null="true"></property>
<many-to-one name="user" column="userid" class="User" unique="true"></many-to-one>
</class>
</hibernate-mapping>

  我们可以看到一个是one-to-one一个是many-to-one的unique。

  分清楚这两个很重要,many-to-one用在保存外键的表,也就是说t_idcard表,one-to-one用在没有保存外键的表,也就是user表.

测试代码:

1、添加关联关系

测试:1:

 public class App {

     private static SessionFactory factory=new Configuration()
.configure()
.addClass(User.class)
.addClass(IdCard.class)
.buildSessionFactory(); @Test
public void test(){ Session session=factory.openSession();
Transaction tx=session.beginTransaction(); User user=new User("caoyc");
IdCard card=new IdCard("510123588413x"); card.setUser(user);
session.save(user);
session.save(card);
tx.commit();
session.close(); }
}

  上面我们通过IdCard来维护关联关系,结果正确

  

测试2:

  下面我们来试一试通过User来维护关联关系,看结果会怎么样?

     @Test
public void test(){ Session session=factory.openSession();
Transaction tx=session.beginTransaction(); User user=new User("caoyc");
IdCard card=new IdCard("510123588413x"); user.setCard(card); session.save(user);
session.save(card);
tx.commit();
session.close(); }

  在数据库中我们可以看到,数据库中表的结构完全一致,而且在t_user中也插入了数据,在t_idcard表中也同样有数据,只不过,t_idcard表中的userid列为null,也就是说,通过user无法维护关联关系

  【总结】:在有外键的一方,可以维护关联关系,而在没有外键的一方无法维护关联关系

测试3:

  我们交换user对象和card对象的保存顺序

 session.save(card);
session.save(user);

  结果数据也能够正常插入到数据库中,结果和测试1相同。那么交换保存顺序是否有其他影响呢?答案是肯定的,虽然数据同样插入进去了,但是在具体插入过程却有不同。

  在测试1中:我们先保存的user,通过insert into语句我们将数据正确插入,然后我们在保存card,而此时的user对象由于已经在数据库中存在,那么必然有主键ID存在,我们在插入到IdCard表中,数据全部完全插入。具体sql语句

 Hibernate: insert into t_user (name) values (?)
Hibernate: insert into t_idcard (cardNo, userid) values (?, ?)

  在测试3中:我们先将card的数据保存到idcard表中,而此时的user的id值为null,所有在插入到idcard中是,userid会是nul

  l

  然后在插入user到t_user表中,那么此时user的主键值已经生成。为了维护关联关系

  系统会有执行一条语句

  update t_idcard set cardNo=?, userid=? where id=?

  所有在测试3中,我们会看到

 Hibernate: insert into t_idcard (cardNo, userid) values (?, ?)
Hibernate: insert into t_user (name) values (?)
Hibernate: update t_idcard set cardNo=?, userid=? where id=?

  【总结】:在保存数据时,我们先保存没有外键的一方,然后在保存有外键的一方,这样执行效率更高

2、解除关联关系

测试1:通过User来解除关联关系

     @Test
public void test(){ Session session=factory.openSession();
Transaction tx=session.beginTransaction(); User user=session.get(User.class, 1);
user.setCard(null); tx.commit();
session.close(); }

  执行的SQL语句

Hibernate: select user0_.id as id1_1_0_, user0_.name as name2_1_0_, idcard1_.id as id1_0_1_, idcard1_.cardNo as cardNo2_0_1_, idcard1_.userid as userid3_0_1_ from t_user user0_ left outer join t_idcard idcard1_ on user0_.id=idcard1_.id where user0_.id=?

  可以看到,此时通过user无法来解除关联关系

测试2:通过idcard来解除关联关系

     @Test
public void test(){ Session session=factory.openSession();
Transaction tx=session.beginTransaction(); IdCard card=session.get(IdCard.class, 1);
card.setUser(null); tx.commit();
session.close(); }

  执行的SQL语句

 Hibernate: select idcard0_.id as id1_0_0_, idcard0_.cardNo as cardNo2_0_0_, idcard0_.userid as userid3_0_0_ from t_idcard idcard0_ where idcard0_.id=?
Hibernate: update t_idcard set cardNo=?, userid=? where id=?

  在数据库中也可看到通过idcard的确能够解除关联关系

3、删除操作

测试1:删除user

     @Test
public void test(){ Session session=factory.openSession();
Transaction tx=session.beginTransaction(); User user=session.get(User.class, 1);
session.delete(user); tx.commit();
session.close(); }

  如果此时将要删除的user数据在t_idcard表中没有对应相应的数据,那么可以删除成功,否则将会抛出异常,意思说有外键约束,该数据无法删除

测试2:删除idcard

     public void test(){

         Session session=factory.openSession();
Transaction tx=session.beginTransaction();
IdCard card=session.get(IdCard.class, 1);
session.delete(card);
tx.commit();
session.close();
}

  结果:删除成功

Question:在上面测试2中,我们删除了t_idcard中的数据,如果我需要当删除了t_idcard中的数据后,同样删除t_user中对应的属性,我们该怎么办呢?

Answer: 那么我们需要设置cascade属性为delete,我们在IdCard.hbm.xml

<many-to-one name="user" column="userid" class="User" unique="true" cascade="delete"></many-to-one>

也就是说,我们在删除对象idCard是,同样对其属性user也做删除动作

外键方式总结:

  1、在有外键的一方,可以维护关联关系,可以建立关联关系,同样也可以解除关联关系,可以任意删除本对象,如果在hbm.xml中设置了cascade="delete",也可以删除关联对象

  2、在没有外键的一方,不可以维护关联关系,所有无法建立关联关系,也无法解除关联关系。在删除过程中,如有没有外键值对应本条数据,可以成功删除,否则会抛出异常

  

二、基于主键的关联方式

  基于外键方式:一个many-to-one(有外键方)和一个one-to-one(无外键方法)

  基于主键方式:两个都是one-to-one

  还是上面的例子,其它我们都不需要改变,我们只需要改变IdCard.hbm.xml就可以,具体代码如下

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.proc.one2one">
<class name="IdCard" table="t_idcard">
<id name="id" type="int" column="id" >
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<property name="cardNo" type="string" column="cardNo" length="20" not-null="true"></property>
<one-to-one name="user" class="User" constrained="true"></one-to-one>
</class>
</hibernate-mapping>

  代码说明:

    1、由于是基于主键方式,所有对应t_idcard表的主键id也是来自于t_user表,所有对应IdCard主键生成策略我们选用foregin,其中还必须指定一个从参数property,表示该主键生成策略基于对象的那个属性,我们这里的属性是user

    2、constrained="true":表示给t_idcard添加一个外键约束,默认为false,不添加外键约束

Hibernate 一对一关联查询的更多相关文章

  1. 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句

    如题: 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句不是一条关联查询语句. 例如: $list = $db->relation(true) ...

  2. MyBatis从入门到放弃三:一对一关联查询

    前言 简单来说在mybatis.xml中实现关联查询实在是有些麻烦,正是因为起框架本质是实现orm的半自动化. 那么mybatis实现一对一的关联查询则是使用association属性和resultM ...

  3. MyBatis:一对一关联查询

    MyBatis从入门到放弃三:一对一关联查询 前言 简单来说在mybatis.xml中实现关联查询实在是有些麻烦,正是因为起框架本质是实现orm的半自动化. 那么mybatis实现一对一的关联查询则是 ...

  4. Mybatis学习4——一对一关联查询方法2------实体作为属性

    实体order和user采用resultMap order package pojo; import java.util.Date; public class Order { private Inte ...

  5. Mybatis学习4——一对一关联查询方法1--创建实体

    创建一个实体继承两个实体之一,另一个实体作为属性 实体1. order package pojo; import java.util.Date; public class Order { privat ...

  6. MyBatis关联查询,一对一关联查询

    数据库E-R关系 实体类 public class City { Long id; String name; Long countryId; Date lastUpdate; } public cla ...

  7. mybatis 使用接口增删改查和两表一对一关联查询

    导包 总配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration ...

  8. MyBatis学习(四)MyBatis一对一关联查询

    一对一关联查询即.两张表通过外键进行关联.从而达到查询外键直接获得两张表的信息.本文基于业务拓展类的方式实现. 项目骨架 配置文件conf.xml和db.properties前几节讲过.这里就不细说了 ...

  9. 04.Hibernate一对一关联

        前言:本文主要介绍使用Hibernate映射一对一的关联关系的两种方式:使用外键映射.使用主键映射. 1.数据库表的一对一关联关系     本文根据客户信息表(tb_customer)和地址信 ...

随机推荐

  1. getResourceAsStream 地址

    getResourceAsStream ()返回的是inputstream getResource()返回:URL Class.getResource("")    返回的是当前C ...

  2. oracle 查看16进制

    DUMP function is useful for this purpose. SQL> select dump(C1) from test; DUMP(C1)--------------- ...

  3. JavaScript中的Array数组详解

    ECMAScript中的数组与其他多数语言中的数组有着相当大的区别,虽然数组都是数据的有序列表,但是与其他语言不同的是,ECMAScript数组的每一项可以保存任何类型的数据.也就是说,可以用数组的第 ...

  4. [xsy2880]取石子游戏

    题意:有$n$堆石子,每堆石子数量相同,以质因数分解给出,不停地从$1$到$n$依次拿石子,使得取完后石子个数为原来的因数(不能不取),当一堆只剩$1$个时结束,问在每堆石子结束的方案数 记石子个数为 ...

  5. (原创)Stanford Machine Learning (by Andrew NG) --- (week 1) Linear Regression

    Andrew NG的Machine learning课程地址为:https://www.coursera.org/course/ml 在Linear Regression部分出现了一些新的名词,这些名 ...

  6. MySQL中变量的定义和变量的赋值使用(转)

    说明:现在市面上定义变量的教程和书籍基本都放在存储过程上说明,但是存储过程上变量只能作用于begin...end块中,而普通的变量定义和使用都说的比较少,针对此类问题只能在官方文档中才能找到讲解. 前 ...

  7. SQL 中 HAVING 用法

    现在 Student表有 如下数据 现需求如下: 查找每个老师的学生的平均年龄且平均年齿大于12 不使用 HAVING SELECT * FROM (SELECT TeacherID, AVG(Age ...

  8. [转载]c++常用字符串操作函数

    原文地址:c++常用字符串操作函数作者:Valsun 函数名: stpcpy 功 能: 拷贝一个字符串到另一个 用 法: char *stpcpy(char *destin, char *source ...

  9. storm一键脚本

    1一键脚本 #!/bin/bash # 1 声明 #-------------------------------------- #请在strom/bin/下执行脚本 #supervisor-host ...

  10. Failed to Attach to Process ID Xcode 解决办法

    方法1. go to the Product menu and find the Edit Scheme menu there. While in Edit Scheme window, select ...