接触Hibernate也有一小段的时间了,愈发的觉得Hibernate是个神奇的东西,为什么这么说呢?因为你可以不懂一行sql,直接面向对象,就可以将数据直接保存到数据库去!!

你还可以保存一个对象,然后一次性的将与它相关的所有数据保存到数据库,比如说,你只需要保存班级对象,就可以将该班级信息和该班级下的所有学生在数据库中形成一堆的记录。

而且都不需要你写sql!!!

有木有很神奇。。。。反正宝宝我是惊呆了。

下面就拿具体的代码实现来讲吧~

首先讲一个简单的  单向一对多的案例(以班级和学生作为案例)

众所周知,Hibernate运用的是一种面向对象的思想,我们想要与数据库相关联,首先我们得必须有与之相对应的实体类

比如说,我有一个学生对象和班级对象,分别对应数据库中的学生表和班级表具体信息如下:

package entity;
/*
*学生表 
*/
import java.io.Serializable; public class Student implements Serializable {
private Integer sid;//学生编号
private String sname;//学生姓名
private String sex;//学生性别 public Student() {
} public Student(String sname, String sex) {
this.sname = sname;
this.sex = sex;
} public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
} }
package entity;
/*
*班级表
*/
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set; public class Grade implements Serializable {
private Integer gid;//班级编号
private String gname;//班级名称
private String gdesc;//班级描述 public Grade() {
} public Grade(String gname, String gdesc) {
this.gname = gname;
this.gdesc = gdesc;
} public Integer getGid() {
return gid;
}
public void setGid(Integer gid) {
this.gid = gid;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
public String getGdesc() {
return gdesc;
}
public void setGdesc(String gdesc) {
this.gdesc = gdesc;
} }

一对多的话,应该是比较好理解的,因为我们可以理解为   一个班级可以以对应多个学生,这就是一对多,既然一个班级对应多个学生的话,那么我们是不是就可以在班级的实体类

中加入一个学生集合和呢?这样是不是更能体现出一对多的关系呢?所以我们对班级实体就有了下面的改造

package entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set; public class Grade implements Serializable {
private Integer gid;//年级编号
private String gname;//年级名称
private String gdesc;//年级描述
//添加一个班级里的学生集合
private Set<Student> stus=new HashSet<Student>(); public Set<Student> getStus() {
return stus;
} public void setStus(Set<Student> stus) {
this.stus = stus;
} public Grade() {
} public Grade(String gname, String gdesc) {
this.gname = gname;
this.gdesc = gdesc;
} public Integer getGid() {
return gid;
}
public void setGid(Integer gid) {
this.gid = gid;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
public String getGdesc() {
return gdesc;
}
public void setGdesc(String gdesc) {
this.gdesc = gdesc;
} }

实体类写完了,我们就该写最关键的配置文件也就是映射文件了(Grade.hbm.xml)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 对应所在的包 -->
<hibernate-mapping package="entity">
<!-- 实体类和数据表的名称 -->
<class name="Grade" table="Grade">
<!-- 实体类中和数据表中所对应的主键 -->
<id name="gid" column="gid">
<!-- 主键生成策略 increment是值找到最大的主键 值,并加1 -->
<generator class="increment" />
</id>
<!-- 非主键属性的配置 -->
<property name="gname" column="gname" />
<property name="gdesc" column="gdesc"/> <!-- 配置多对一配置信息 -->
<set name="stus" table="Student" >
<!-- 多方的外建值 -->
<key column="gid"></key>
<one-to-many class="entity.Student"/>
</set>
</class>
</hibernate-mapping>

这样我们就完成了一对多的配置了,此时,我们不用对Student.hbm.xml做任何操作,下面可以测试了

//单向一对多案例(一个班级对应多个学生)
public static void DOneToManyAdd(){
//准备session
Session session=HibernateUtil.currentSession();
//开启事务
Transaction tx = session.beginTransaction();
//创建一个班级
Grade grade=new Grade("S1261","无敌的Y1261班");
//准备几个学生
Student stu1=new Student("微热的雪","女");
Student stu2=new Student("巴黎的雨季","男");
//设置班级里的学生
grade.getStus().add(stu1);
grade.getStus().add(stu2); //保存
session.save(grade);
session.save(stu1);
session.save(stu2); //提交事务
tx.commit();
//关闭连接
HibernateUtil.closeSession();
}

执行这些代码后可以在控制台看到如下信息

这个时候,你的数据库中便有了如下信息

可以从上面的测试代码中看出,我并没有手动的指定学生所在的班级,但是因为有映射文件,Hibernate会自动的检索到所在的班级并自行的发送sql语句到数据库进行持久化操作。

这就是Hibernate的强大之处,当然,这只是一个最简单的例子,下面就跟着我看看更加有趣的例子吧!

Hibernate关系映射二之   单向多对一关系映射

多对一关系映射也同样的好理解,比如,多个学生可以同时处于一个班级下,这就是单向的多对一的关系,所以我们就可以想到在学生表中加入一个班级属性

package entity;

import java.io.Serializable;

public class Student implements Serializable {
private Integer sid;//学生编号
private String sname;//学生姓名
private String sex;//学生性别
//创建一个班级
private Grade grade; public Grade getGrade() {
return grade;
} public void setGrade(Grade grade) {
this.grade = grade;
} public Student() {
} public Student(String sname, String sex) {
this.sname = sname;
this.sex = sex;
} public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
} }

因为是单向的多对一,所以我们只需要在多的一方,也就是学生方的配置文件中进行修改,班级方的配置文件保持原始(也就是没有set标签的时候)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="entity">
<class name="Student" table="Student">
<id name="sid" column="sid">
<generator class="increment" />
</id>
<property name="sname" column="sname" />
<property name="sex" column="sex"/>
<!-- 配置多对一的关系映射 -->
<many-to-one name="grade" class="entity.Grade" column="gid"></many-to-one>
</class>
</hibernate-mapping>

同样,我们做一个单向多对一的添加操作

//单向多对一添加案例(多个学生对应一个班级)
public static void DManyToOneAdd(){
//准备session
Session session=HibernateUtil.currentSession();
//开启事务
Transaction tx = session.beginTransaction();
//创建一个班级
Grade grade=new Grade("S2222班","挺6的S2222班");
//准备几个学生
Student stu1=new Student("恩恩","男");
Student stu2=new Student("呵呵","女");
//设置学生所在的班级
stu1.setGrade(grade);
stu2.setGrade(grade);
//保存
session.save(grade);
session.save(stu1);
session.save(stu2);
//提交事务
tx.commit();
//关闭连接
HibernateUtil.closeSession();
}

注意!!!此时的Hibernate生成的sql语句与一对多时是不一样的!

数据库中同样也是有相对应的记录

经过上面两个案例的展示,可能有同学就会有疑问了,既然多个学生可以属于一个班级,一个班级又可以有多个学生,那么他们俩之间到底可以设为 什么关系呢?

此时,我们就可以设置为  双向的一对多的关系了。因为班级和学生是一个双向的关系,而且一个班级又有多个学生

这时我们完整的配置文件就是以上的两个总和了

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="entity">
<class name="Student" table="Student">
<id name="sid" column="sid">
<generator class="increment" />
</id>
<property name="sname" column="sname" />
<property name="sex" column="sex"/>
<!-- 配置多对一的关系映射 -->
<many-to-one name="grade" class="entity.Grade" column="gid" ></many-to-one>
</class>
</hibernate-mapping>

Grade.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 对应所在的包 -->
<hibernate-mapping package="entity">
<!-- 实体类和数据表的名称 -->
<class name="Grade" table="Grade">
<!-- 实体类中和数据表中所对应的主键 -->
<id name="gid" column="gid">
<!-- 主键生成策略 increment是值找到最大的主键 值,并加1 -->
<generator class="increment" />
</id>
<!-- 非主键属性的配置 -->
<property name="gname" column="gname" />
<property name="gdesc" column="gdesc"/> <!-- 配置多对一配置信息 -->
<set name="stus" table="Student" >
<!-- 多方的外建值 -->
<key column="gid"></key>
<one-to-many class="entity.Student"/>
</set>
</class>
</hibernate-mapping>

测试数据

//双向添加案例
private static void SAdd(){
//准备session
Session session=HibernateUtil.currentSession();
//开启事务
Transaction tx = session.beginTransaction();
//创建一个班级
Grade grade=new Grade("S2222班","挺6的S2222班");
//准备几个学生
Student stu1=new Student("巴黎的雨季","男");
Student stu2=new Student("微热的雪","女");
//设置班级下的学生
grade.getStus().add(stu1);
grade.getStus().add(stu2);
//为学生设置班级
stu1.setGrade(grade);
stu2.setGrade(grade);
//保存
session.save(grade);
session.save(stu1);
session.save(stu2);
//提交事务
tx.commit(); //关闭连接
HibernateUtil.closeSession();
}

细心的同学会发现,当我执行了上面的代码时,效果与我设置多对一和一对多的效果一样,而且这还比较的繁琐和复杂,所以这并不是双向关系的优势

这里我们就要用到cascade(级联)的属性了   设置级联的属性后,因为有 双向的关系,所以当你只添加班级的时候Hibernate会自动的添加班级下的学生

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="entity">
<class name="Student" table="Student">
<id name="sid" column="sid">
<generator class="increment" />
</id>
<property name="sname" column="sname" />
<property name="sex" column="sex"/>
<!-- 配置多对一的关系映射 -->
<many-to-one name="grade" class="entity.Grade" column="gid" cascade="all"></many-to-one>
</class>
</hibernate-mapping>

Grade.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 对应所在的包 -->
<hibernate-mapping package="entity">
<!-- 实体类和数据表的名称 -->
<class name="Grade" table="Grade">
<!-- 实体类中和数据表中所对应的主键 -->
<id name="gid" column="gid">
<!-- 主键生成策略 increment是值找到最大的主键 值,并加1 -->
<generator class="increment" />
</id>
<!-- 非主键属性的配置 -->
<property name="gname" column="gname" />
<property name="gdesc" column="gdesc"/> <!-- 配置多对一配置信息 -->
<set name="stus" table="Student" cascade="all" inverse="true">
<!-- 多方的外建值 -->
<key column="gid"></key>
<one-to-many class="entity.Student"/>
</set>
</class>
</hibernate-mapping>

这样当我们设置级联的属性后,测试代码如下

//双向添加案例(添加班级自动添加班级下的学生)
private static void SAdd(){
//准备session
Session session=HibernateUtil.currentSession();
//开启事务
Transaction tx = session.beginTransaction();
//创建一个班级
Grade grade=new Grade("S2222班","挺6的S2222班");
//准备几个学生
Student stu1=new Student("巴黎的雨季","男");
Student stu2=new Student("微热的雪","女");
//设置班级下的学生
grade.getStus().add(stu1);
grade.getStus().add(stu2);
//为学生设置班级
stu1.setGrade(grade);
stu2.setGrade(grade);
//保存(设置级联属性,自动关联该班级下的学生)
session.save(grade); //提交事务
tx.commit(); //关闭连接
HibernateUtil.closeSession();
}

这样,我们只用写save(grade) 保存班级,这时Hibernate会生成如下代码

至此,基本上就讲完了Hibernate中单向关系映射的知识点了,明天为大家讲解关于双向多对多关系映射的知识点。

详谈Hibernate框架关系映射!的更多相关文章

  1. Hibernate框架关系映射一对多双向关联

    直入主题,首先大配置常规配置, 这里住要说关联关系,大配置不多少,而且jar包默认添加好,笔者用的是idea2016. 然后我们知道关联关系主要是在小配置添加节点来配置属性.个人认为关联映射,就是对应 ...

  2. hibernate(3) —— 关系映射

    hibernate中关系映射指的是实体类与实体类间的关系.和数据库中表与表之间的关系类似,有一对一,多对一,一对多,多对多四种映射关系. 一:一对一映射 两个对象之间是一对一的关系,如人和身份证之间是 ...

  3. Hibernate注解关系映射

    Hibernate Annotation关系映射的几种类型映射用法及使用方法(说明:以前实例的实体是user和role,主键分别是userid和roleid)   1)一对一外键关联映射(单向) @O ...

  4. hibernate 实体关系映射笔记

    @经常使用属性说明:     @Entity:实体类     @Table:指定相应数据表     @Id:主键,使用能够为null值的类型,假设实体类没有保存到数据库是一个暂时状态     @Col ...

  5. hibernate对象关系映射( 一对一,一对多,多对一,多对多的单向,双向映射 ——)

    对象之间的关系: 关系映射之间的关系只的是对象之间的关系,并不指数据库表的关系(外键关系)这儿解决的问题是当对象之间的关系之一时,数据库表该如何映射,编程上如何对待. 一对一(主键关联,和单向的外键关 ...

  6. Hibernate 对象关系映射文件

    简介: POJO 类和关系型数据库之间的映射可以用一个 XML 文档来定义 通过 POJO 类的数据库映射文件,Hibernate 可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据 ...

  7. Hibernate表关系映射之一对一映射

    一.数据表的映射关系 在数据库领域中,数据表和数据表之间关系一般可以分为如下几种: 一对一:比如公民和身份证的关系,一个人只有一张身份证,同时每张身份证也仅仅对应一个人! 一对多:比如客户和订单之间的 ...

  8. MyBatis框架——关系映射(一对多、多对多、多对一查询)

    关系映射 一.映射(多)对一.(一)对一的关联关系 1).使用列的别名 ①.若不关联数据表,则可以得到关联对象的id属性 ②.若还希望得到关联对象的其它属性.则必须关联其它的数据表 1.创建表: 员工 ...

  9. Hibernate实体关系映射(OneToMany单边)——完整实例

    单边一对多关系:电子邮件管理 单边一对多关系:指一方有集合属性,包含多个多方,而多的一方没有一方的引用. 比如:用户(一)与电子邮件(多).一个用户可以有多个电子邮件记录. 目的:通过OneToMan ...

随机推荐

  1. [每天默写一个算法]KMP

    [每天默写一个算法]KMP 作业要求:默写String的KMP算法. KMP是经典的字符串匹配算法.复杂度为O(n+m) public static class StringKMP { /// < ...

  2. Spring-Context之七:使用p-namesapce和c-namespace简化bean的定义

    在Spring中定义bean的方式多种多样,即使使用xml的方式来配置也能派生出很多不同的方式. 比如如下的bean定义: 1 2 3 4 5 6 7 8 9 10 11 12 <beans x ...

  3. html5 Application Cache——加快简历二次访问速度

    上篇博客(在github上写个人简历——最简单却又不容易的内容罗列)介绍了我在github上放的一个个人在线简历,有朋友看了后告诉我一个很大缺陷,使用github挺慢的,每次看的时候都很慢,第一反应这 ...

  4. git 修改管理

    查看修改: 撤销某一文件的修改(还没提交): 撤销所有文件的修改: git checkout .

  5. 纯CSS实现3D按钮效果

    今天分享一个用纯CSS实现的3D按钮.css巧妙利用了box-shadow来实现3D物体的立体感,当按钮按下的时候再去修改box-shadow和top值.让人感觉有一种按钮被按下的感觉.css代码非常 ...

  6. EF架构~linq to entity的随机排序问题

    回到目录 对于从linq to sql迁移过来的开发者,对随机排序不会感到陌生,直接为datacontext添加一个方法再配合反射就可以实现随机排序了,代码如下: /// <summary> ...

  7. Jquery判断数组中是否包含某个元素$.inArray()的用法

    判断数组里面是否包含某个元素可以使用 $.inArray("元素(字符串)",数组名称) 进行判断 ,当存在该元素(字符串)时,返回该元素在数组的下标,不存在时返回 -1 示例代码 ...

  8. DOM对象模型四大基本接口

    本文向大家描述一下DOM对象模型的四个基本接口,在DOM对象模型接口规范中,有四个基本的接口:Document,Node,NodeList以及NamedNodeMap. 在DOM对象模型接口规范中,有 ...

  9. 深入理解PHP内核(九)变量及数据类型-静态变量

    原文链接:http://www.orlion.ga/251/ 通常静态变量是静态分配的,他们的生命周期和程序的生命周期一样长,只有在程序退出后才结束生命周期,这和局部变量相反,有的语言中全局变量也是静 ...

  10. 深入理解javascript作用域系列第二篇——词法作用域和动态作用域

    × 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极 ...