详谈Hibernate框架关系映射!
接触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框架关系映射!的更多相关文章
- Hibernate框架关系映射一对多双向关联
直入主题,首先大配置常规配置, 这里住要说关联关系,大配置不多少,而且jar包默认添加好,笔者用的是idea2016. 然后我们知道关联关系主要是在小配置添加节点来配置属性.个人认为关联映射,就是对应 ...
- hibernate(3) —— 关系映射
hibernate中关系映射指的是实体类与实体类间的关系.和数据库中表与表之间的关系类似,有一对一,多对一,一对多,多对多四种映射关系. 一:一对一映射 两个对象之间是一对一的关系,如人和身份证之间是 ...
- Hibernate注解关系映射
Hibernate Annotation关系映射的几种类型映射用法及使用方法(说明:以前实例的实体是user和role,主键分别是userid和roleid) 1)一对一外键关联映射(单向) @O ...
- hibernate 实体关系映射笔记
@经常使用属性说明: @Entity:实体类 @Table:指定相应数据表 @Id:主键,使用能够为null值的类型,假设实体类没有保存到数据库是一个暂时状态 @Col ...
- hibernate对象关系映射( 一对一,一对多,多对一,多对多的单向,双向映射 ——)
对象之间的关系: 关系映射之间的关系只的是对象之间的关系,并不指数据库表的关系(外键关系)这儿解决的问题是当对象之间的关系之一时,数据库表该如何映射,编程上如何对待. 一对一(主键关联,和单向的外键关 ...
- Hibernate 对象关系映射文件
简介: POJO 类和关系型数据库之间的映射可以用一个 XML 文档来定义 通过 POJO 类的数据库映射文件,Hibernate 可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据 ...
- Hibernate表关系映射之一对一映射
一.数据表的映射关系 在数据库领域中,数据表和数据表之间关系一般可以分为如下几种: 一对一:比如公民和身份证的关系,一个人只有一张身份证,同时每张身份证也仅仅对应一个人! 一对多:比如客户和订单之间的 ...
- MyBatis框架——关系映射(一对多、多对多、多对一查询)
关系映射 一.映射(多)对一.(一)对一的关联关系 1).使用列的别名 ①.若不关联数据表,则可以得到关联对象的id属性 ②.若还希望得到关联对象的其它属性.则必须关联其它的数据表 1.创建表: 员工 ...
- Hibernate实体关系映射(OneToMany单边)——完整实例
单边一对多关系:电子邮件管理 单边一对多关系:指一方有集合属性,包含多个多方,而多的一方没有一方的引用. 比如:用户(一)与电子邮件(多).一个用户可以有多个电子邮件记录. 目的:通过OneToMan ...
随机推荐
- FastUI快速界面原型制作工具
FastUI是一款快速制作应用程序界面原型的小工具,它之所以快,是因为它体积小巧.功能简洁实用. 在真正的应用程序(包括winform.手机app.网站等)开始编码之前,一般要先设计出原型,以便确认需 ...
- 据说每个大牛、小牛都应该有自己的库——Ajax
蹉跎到今天终于要写Ajax部分了,平时工作中除了选择器我用jQuery的最多的就是ajax,所以这部分在自己的框架中必不可少. XMLHttpRequest 我以为对每个使用过Ajax的人来说XMLH ...
- Spring Trasnaction管理(1)- 线程间事务隔离
问题导读 Spring中事务是如何实现的 Spring中各个线程间是如何进行连接.事务隔离的 Spring事务配置 Spring的事务管理应该是日常开发中总会碰到的,但是Spring具体是怎么实现线程 ...
- IOS 多线程05-OperationQueue 、GCD详解
注:本人是翻译过来,并且加上本人的一点见解. 1. 开始 目前在 iOS中有两套先进的同步 API 可供我们使用:操作队列OperationQueue和 GCD .其中 GCD 是基于 C 的底层 ...
- 关于redis启动流程介绍
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/94.html?1455870894 1. 准备运行环境 * 设置oom h ...
- JDBC操作数据库,第一:jsp插入mysql数据库,坎坷摸索分享
JSP连接数据库,坎坷摸索了好久,现在终于做好了,分享一下,希望对更多热爱编程学习的人有所帮助!!!谢谢 第一:首先准备的就是已经安装好Mysql,这里不做多叙述,百度可以做到. 然后在mysql数据 ...
- Android笔记——Android框架
本篇将站在顶级的高度--架构,来看android.我开篇就说了,这个系列适合0基础的人且我也是从0开始按照这个步骤来 学的,谈架构是不是有点螳臂挡车,自不量力呢?我觉得其实不然,如果一开始就对整个an ...
- Struts2学习笔记 - HelloWorld总结
相信网上已经有很多关于struts2的HelloWorld可参考,我这里就不重复了,没个学struts2的人都会做过很多个HelloWorld,而我这里就总结一下一个简单的HelloWorld 我在一 ...
- 加载的过程中图片变形了? --教你自定义自动适配图片宽高比的RatioLayout
很多同行在开发中可能会遇到这样的问题,就是在加载图片的时候会出现图片变形的问题.其实这很可能就是你的图片宽高比和图片所在容器的宽高比不匹配造成的.比如说图片的宽为200,高为100.宽高比就是2,那么 ...
- 分享10条Visual Studio 2012的开发使用技巧
使用Visual Studio 2012有一段时间了,并不是追赶潮流,而是被逼迫无可奈何.客户要求的ASP.NET MVC 4的项目,要用.NET 4.5来运行.经过一段时间的摸索,得到一点经验和体会 ...