详谈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中单向关系映射的知识点了,明天为大家讲解关于双向多对多关系映射的知识点。

时间: 2024-10-08 00:08:44

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

Hibernate框架关系映射

接触Hibernate也有一小段的时间了,愈发的觉得Hibernate是个神奇的东西,为什么这么说呢?因为你可以不懂一行sql,直接面向对象,就可以将数据直接保存到数据库去!! 你还可以保存一个对象,然后一次性的将与它相关的所有数据保存到数据库,比如说,你只需要保存班级对象,就可以将该班级信息和该班级下的所有学生在数据库中形成一堆的记录. 而且都不需要你写sql!!! 有木有很神奇....反正宝宝我是惊呆了. 下面就拿具体的代码实现来讲吧~ 首先讲一个简单的  单向一对多的案例(以班级和学生作为

hibernate 实体关系映射笔记

@常用属性说明: @Entity:实体类 @Table:指定对应数据表 @Id:主键,使用可以为null值的类型,如果实体类没有保存到数据库是一个临时状态 @Column:配置普通属性,除了主键外,java基本类型的属性 @Base:普通属性的加载方式 @GeneratedValue:主键生成策略 @Temporal:日期类型(DATE,TIME还是TIMESTAMP),如果属性类型是java.util.Date(是以上3个类的父类)类型时才需要使用该@声明具体的日期类型 @Transient:

hibernate 对象关系映射文件详解

POJO 类和数据库的映射文件*.hbm.xml POJO类和关系数据库之间的映射可以用一个XML文档来定义. 映射文件的扩展名为.hbm.xml 在运行时Hibernate将根据这个映射文件来生成各种SQL语句 通过POJO类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系 映射文件说明 hibernate-mapping 类层次:class 主键:id 基本类型:property 实体引用类: many-to-one

Hibernate Annotation关系映射, 级联cascade属性

Hibernate Annotation关系映射, 级联cascade属性一. Hibernate Annotation关系映射 1.一对一外键关联映射(单向) 2.一对一外键关联映射(双向) 3.一对一主键关联映射(不重要)在这不演示 在实际中很少用,使用注解@PrimaryKeyJoinColumn 意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试使用 注解一对一主键关联映射,在生成表的时候,数据库中并没有生成关联,使用XML 映射可以生成.Annotation注解一对

hibernate继承关系映射和java反射机制的运用

转:http://blog.csdn.net/derpvailzhangfan/article/details/1957946 ,感谢博主分享 Notes:hibernate元数据的运用:uuid的概念:java的反射机制,“因为抽象类无法new出对象来,所以就要用java反射机制”,“TcommTable tomm = (TcommTable) Class.forName(allName).newInstance();”: hibernate继承关系映射大概有5种,这5种继承关系映射里面,我觉

ORM进阶之Hibernate中关系映射

ORM进阶之 ORM简介 ORM进阶之Hibernate简介及框架搭 ORM进阶之Hibernate的三大对象 ORM进阶之Hibernate中对象的三大状态解析 ORM进阶之Hibernate中一对一的关系映射 映射可以说是在hibernate中非常重要的一个内容,通过映射可以让程序员不再思考复杂的sql语句,而是更加的专注于业务逻辑的实现.映射通过一个xml配置文件完成并且我们可以对他进行修改!下边我们来看一下如何完成映射的! 单表映射 每个实体对应一张表,跟其他的实体没有关联关系,这是最简

hibernate 表关系映射详解之一对多

一对多 传统模式:jdbc连接数据库的传统模式下,是通过主键连接外键实现一对多关系的映射, 其数据库中表的对应关系是在多方加入一方的主键,而后形成外键连接. Hibernate:引入hibernate框架后,通过类的形式来表示一对多的关系. 举例:订单与订单详细的关系,一个订单包含多个商品,多个商品属于一个订单,两者的关系是一对多的关系. 实现原理: 面向对象实现------ 在order类中加入item类的set集合 ,表示在订单类中包含有多个订单详细(集合表示). 层次结构: 步骤一:编写实

Hibernate对象关系映射(一)

Hibernate的本质是对象关系映射,ORM实现了将对象的变化保存到数据库中.以前我们对关系表操作,执行增CRUD.现在我们不在对关系表进行操作,而是直接对对象操作.对象关系的映射有以下几种 基本图形 图1 一对一映射 分两种情况 主键 唯一外键 1主键 两个对象具有相同的主键,不再有额外字段维护他们的关系 图2 Person和Card之间,他们的主键是相同的 2唯一外键 其实是用来表示多对一的,如果加上唯一限制,就可以表示一对一关联 图3 图3可以看到卡号在person中充当了一个外键. 根

hibernate继承关系映射方法(三)--每个具体类一张表TPC

TPC:所谓是"每个具体类一张表(table per concrete class)"的意思是:使继承体系中每一个子类都对应数据库中的一张表.每一个子类对应的数据库表都包含了父类的信息,并且包含了自己独有的属性.每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段.这种策略是使用<union-subclass>标签来定义子类的. 注意:三个类+一个父类映射文件+两张表 student表 worker表 测试工程: Person.java