1.many-to-one

以学生和部门之间的关系为例:

Department.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="com.xidian.domain">
<class name="Department" lazy="false">
<!-- 配置主键属性 -->
<id name="id" type="java.lang.Integer">
<!-- 生成策略 -->
<generator class="identity">
</generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="64" not-null="true"/>
</property>
</class>
</hibernate-mapping>

student.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="com.xidian.domain">
<class name="Student">
<id name="id" type="java.lang.Integer">
<generator class="identity">
</generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="64"/>
</property>
<!-- 对于private Department dept;就不能使用property
column="dept_id" 表示将来自动生成的表的外键名-->
<many-to-one name="dept" column="dept_id"/>
</class>
</hibernate-mapping>

应用:

Student stu1=new Student();
stu.setName("宋江");

Student stu2=new Student();
stu.setName("宋江");

Department d=new Department();
d.setName("财务部");

stu1.setDept(d);//指定该学生是哪个部门

stu2.setDept(d);

s.save(d);
s.save(stu1);
s.save(stu2);
如果先保存学生再保存部门,也是可以的。在保存学生的时候部门还不存在,外键会设置为空,然后再保存部门,当commit提交事务的

时候发现它们具有映射关系,就会再来设置学生的外键引用(这种情况下hibernate会多一条update语句)。

在应用多对一的情况时会发现,只做了many到one单方向的映射,只是能将多个学生通过外键关系添加到一个部门中。

问题:反过来如果需要通过一个部门号(1),来获取该部门的所有学生?如果用上面的many to one形式需要hql语句进行查询:

String hql=”from Student where dept.id=1”

这时就需要one-to-many的反方向查询。

在这里引入懒加载的概念:

简述: 多表查询时,当我们查询一个对象的时候,在默认情况下,返回的只是该对象的普通属性,当用户去使用对象属性时,

才会向数据库发出再一次的查询.这种现象我们称为 lazy现象.

student=(Student) s.get(Student.class, 3);

System.out.println(student1.getName()+" 所在部门="
      +student1.getDept().getName());//当session还在,依然可以向数据库发sql语句。可是假若我们只是获取到student对象,

                   //没有对对象属性进行查询,当session关闭后就不可以再向数据库发sql语句,无法查询。

解决方法:

1.显示初始化代理对象 Hibernate.initized( student.getdept())

2.修改对象关系文件 class属性 lazy  改写 lazy=false

3.通过过滤器(web项目) openSessionInView     (从上面的例子可以看出,当session关闭后,就不能向数据库发sql语句,那么就扩大session的范围

                    这个后面会详细介绍)

2.one-to-many

在one那一方配置<set ></set>

在many一方必须要一个外键指向one这方的属性,所以配置<many-to-one>是必须的。

而one这方是否配置<one-to-many>看是否需要指定一个集合属性指向回many一方,这样从主表一方获取从表的属性是非常方便的。

在这里再看通过获取到部门查看学生信息:

Department department1=(Department) s.get(Department.class, 3);
//取出该部门的学生
Set<Student> stus= department1.getStus();
for(Student ss: stus){
System.out.println(ss.getName());

}

添加学生
Department department=new Department();
department.setName("业务部门");

Student stu1=new Student();
stu1.setName("顺平");
Student stu2=new Student();
stu2.setName("小明");

Set<Student> sets=new HashSet<Student>();
sets.add(stu1);
sets.add(stu2);
department.setStus(sets);

s.save(department);              //这里涉及到级联操作,需要在Department.hbml.xml中配置

               //<set name="stus" cascade="save-update">这样将在保存department的时候将

               //部门中的学生一并保存。

3.one-to-one

一对一有有两种方式  区别是基于主键的情况是会在主键之间形成映射关系

(从表的某一属性既是自身表的主键也是引用到其他表的外键,主键充当外键),基于外键是以非主键的外键形成映射关系。

(1) 基于主键的一对一

一定要设置constrained=”true” 才能形成外键约束关系

一对一关系中典型的问题是人与身份证的关系。

Person p1=new Person();
p1.setId(1224);
p1.setName("xkj");

IdCard idCard=new IdCard();
idCard.setValidateDte(new Date());

idCard.setPerson(p1);//表示idCard对象是属于p1这个对象.
           //p1.setIdCard(idCard);错误方式
s.save(p1);     //先保存人
s.save(idCard);

数据库中结果:

idCard表

person表

这里有两个注意问题:

1.如果我使用p1.setIdCard(idCard)来指定person和idCard之间的关系会出错:

只能使用idCard.setPerson(p1)方式。关系应该是在idCard上有一个外键指向person,而不是相反。报错行在

说明在保存idCard的时候,外键person属性是空而导致错误。

2.如果调换保存顺序:

s.save(idCard); //先保存卡

s.save(p1);  

报出错误:

java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]

INSERT 语句与 FOREIGN KEY 约束"FKB8CDF6CB2A59F864"冲突。该冲突发生于数据库"test",表"dbo.person", column 'id'。  
解析理论:外键约束,比如B表存在一个字段b,有外键约束,引用于A表的主键a,那么在向B表插入数据时,

字段b必须为A表中a已经存在的值,如过向b中存放一个a中没有的值,则会报违反外键约束。

可是如果回头看one-to-many那个例子中却发现学生表中有外键指向部门的主键,先保存学生再保存部门也是可以的,

只是会多一个update语句,这是hibernate的优化机制。可是放在这个地方却不可以,why?

希望大家指点填坑!

(二)基于外键的一对一

只改动上面的IdCard.hbm.xml映射文件

<id name=”id” type=”java.lang.Integer”>

<generator class=”assigned” />

</id>

<property ame=”VaidateDate” type=”java.util.Date”>

<column name=”validateDate” />

</property>

<many-to-one  name=”person”  unique=”true” />   //person是外键 在idCard表中会生成这个外键,它指向的是主表的主键id

在idCard这边,可看成是many-to-one的一个特例,加unique保证唯一。

Person p1=new Person();
p1.setId(122);
p1.setName("xkj");

IdCard idCard=new IdCard();
idCard.setId(1905);
idCard.setValidateDte(new Date());

idCard.setPerson(p1);//表示idCard对象是属于p1这个对象.

s.save(p1); //先保存人
s.save(idCard);

数据库结果:

在这里我依然测试了前面出现的两个问题:

第一个问题没有报错,只是idCard的person外键为空。

第二个问题hibernate又给解决了,同样是多一句update语句。

4.many-to-many

学生和课程是经典的多对多的案例。

在实际开发中,如果出现了many-to-many关系,我们应该将其转换成两个one-to-many 或者 many-to-on, 这个程序好控制,同时不会有冗余。

在stucourse中有两个外键分别指向student和course

//添加一个学生,一门课程,选课
Student stu1=new Student();
stu1.setName("小明");

Course course=new Course();
course.setName("java");

StuCourse sc=new StuCourse();

sc.setCourse(course);
sc.setStudent(stu1);

//顺序保存.
s.save(stu1);
s.save(course);
s.save(sc);

数据库结果:

Hibernate(七)__多对一 、一对多、 一对一、多对多的更多相关文章

  1. Hibernate关联关系配置(一对多,一对一,多对多)

    一对多 创建两个类  Manager(一这一端) Worker(多这一端)  即一个经理下有多个员工 package com.hibernate.n21; import java.util.HashS ...

  2. 【转】hibernate映射(单向双向的一对多、多对一以及一对一、多对一)

    多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一 一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 也就是说一对多和多对一的映射策略是一样的,只是站 ...

  3. Hibernate框架--关联映射,一对多,多对多 inverse cascade

    回顾Hibernate: 1. hibernate开发环境搭建 ----> 引入jar: hibernate.jar + required + jpa + 驱动包 ---> hiberna ...

  4. 2.2、Hibernate用注解方式实现一对多、多对多关系

    一.一对多关系 1.在上一篇日志中用.xml配置文件项目基础上,再往lib目录先添加一个包-hibernate-jpa-2.0-api-1.0.0.Final.jar 2.新建一个com.st.bea ...

  5. Hibernate用注解方式实现一对多、多对多关系

    一.一对多关系 1.在上一篇日志中用.xml配置文件项目基础上,再往lib目录先添加一个包-hibernate-jpa-2.0-api-1.0.0.Final.jar 2.新建一个com.st.bea ...

  6. Hibernate入门(三)—— 一对多、多对多关系

    一.一对多关系 1.概念 ​ 一对多关系是关系型数据库中两个表之间的一种关系.通常在数据库层级中,两表之间是有主外键关系的.在ORM中,如何通过对象描述表之间的关系,是ORM核心. 2.Hiberna ...

  7. hibernate:inverse、cascade,一对多、多对多详解

    1.到底在哪用cascade="..."? cascade属性并不是多对多关系一定要用的,有了它只是让我们在插入或删除对像时更方便一些,只要在cascade的源头上插入或是删除,所 ...

  8. Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!

    前面讲了Spring Boot 使用 JPA,实现JPA 的增.删.改.查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用.JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层 ...

  9. 一对多(多对一)关系中的inverse和cascade属性

    转载请标明出处 http://www.cnblogs.com/haozhengfei/p/6049276.html 首先说一下inverse: "inverse" 直译过来就是&q ...

随机推荐

  1. java三大循环:for、while、do...while

    1.while和do...while的区别: while 与 do...while之间的区别:如果布尔表达式第一次执行的结果就为false,那么while循环一次也不执行:do...while循环会执 ...

  2. andriod adt和andriod sdk

    今天搭建appium的环境,没有太明白andriod adt和andriod sdk分别是什么东西,经过与开发沟通,大致了解如下,这里记录一下,免得过几天就搞忘了. andriod adt是一个插件, ...

  3. Android内存回收机制

    退出但不关闭: 这是Android对于Linux的优化.当 Android 应用程序退出时,并不清理其所占用的内存,Linux 内核进程也相应的继续存在,所谓“退出但不关闭”.从而使得用户调用程序时能 ...

  4. php的mysql\mysqli\PDO(一)mysql

    原文链接:http://www.orlion.ga/1140/ 工作中数据库的操作都被封装好了,这些怎么用的都快忘了干脆写篇博客重新复习下,以后要是再忘记了可以看这篇文章. PHP 5.5.0 起已废 ...

  5. nodejs+phantomjs+七牛 实现截屏操作并上传七牛存储

    近来研究了下phantomjs,只是初涉,还谈不上深入研究,首先介绍下什么是phantomjs. 官网上的介绍是:”PhantomJS is a headless WebKit scriptable ...

  6. 在office2010的ppt中加入音乐

    Microsoft office Powerpoint,是微软公司设计的演示文稿软件.用户不仅可以在投影仪或者计算机上进行演示,也可以将演示文稿打印出来,制作成胶片,以便应用到更广泛的领域中.利用Mi ...

  7. Unity3D 开发之shader教程(浅谈光照之漫反射diffuse)

    在游戏开发过程中,光照应该是必不可少部分,当然,这是指大多数的稍微大型一些的3D游戏会需要,给模型或者山山水水加上光照,会看上去更加的真实,获得更好的体验.一个本身不发光物体显示什么颜色,在于本身反射 ...

  8. [转载]TFS源代码管理8大注意事项

    目录 1. 使用TFS进行源代码管理 2. 如果代码没放在源代码管理软件里,等于它不存在 3. 要早提交,常提交,并且不要觉得麻烦 4. 提交前要检查你更改了什么 5. 写提交信息时一定要认真 6. ...

  9. Testing - 测试基础 - 探索

    定义 探索性测试(Exploratory Testing)是一种自由的软件测试风格,强调测试人员同时展开测试学习,测试设计,测试执行和测试结果评估等活动,以持续优化测试工作. 其特征有:即兴发挥,快速 ...

  10. Windows下Eclipse提交MR程序到HadoopCluster

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 欢迎转载,转载请注明出处. 以前Eclipse上写好的MapReduce项目经常是打好包上传到Hadoop测试集 ...