三沣开发知识 购物 网址 游戏 小说 歌词 地图 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 租车 短信 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题
autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml
html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
  IT知识库 -> 架构设计 -> 详谈Hibernate框架关系映射! -> 正文阅读
 

[架构设计]详谈Hibernate框架关系映射!

详谈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中单向关系映射的知识点了,明天为大家讲解关于双向多对多关系映射的知识点。
  架构设计 最新文章
spring boot实现ssm(2)功能
java 企业站源码 兼容手机平板PC 自适应响应
Serverless无服务应用架构纵横谈
理论篇:关注点分离(Separation of concern
Struts 2 入门
spring boot实现ssm(1)功能
函数指针
GPS部标监控平台的架构设计(十一)
Warrior!之家与Warrior!博客网站发布
一个高性能、轻量级的分布式内存队列系统
上一篇文章      下一篇文章      查看所有文章
加:2016-08-12 17:45:42  更:2017-05-16 02:53:06 
 
技术频道: 站长资讯 .NET新手区 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA Visual Studio ASP.NET MVC .NET控件开发 Entity Framework WinRT/Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动设计 Html/Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP Oracle ERP Dynamics CRM K2 BPM 信息安全 企业信息化其他 Android开发 iOS开发 Windows Phone Windows Mobile 其他手机开发 敏捷开发 项目与团队管理 软件工程其他 SQL Server Oracle MySQL NoSQL 其它数据库 Windows 7 Windows Server Linux
脚本语言: vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程
网站开发: CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年7日历
2018-7-22 13:13:08
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库