hibernate多对一关联映射两种形式的理解

关联是类(类的实例)之间的关系,表示有意义和值得关注的连接。

多对一单向和多对一双向关联:

单向:多对一单向是只用维护多的一方,例如一家厂商(Factory)可以生产多种产品(Product),只用在Product实体类和配置文件中配置即可。
在Product实体属性类中,需要有Factory属性,而不再需要外键这个属性,因为关联外键的配置在配置文件中many-to-one。

双向:多对一双向关联需要双方都维护对方,例如班级(Class)和学生(Student)之间的关系,需要在Class实体类和Class映射文件中配置维护Student,
one-to-many,在Class实体类属性中,需要用Set集合存储Student。
也需要在Student实体类和Student映射文件中配置维护Class,many-to-one,在Product实体属性中,同样需要有Factory属性。

文件结构:

hibernate核心配置文件

Hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
      <!-- 配置数据库连接驱动类 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 配置数据库连接字符串 -->
        <property name="connection.url"><![CDATA[jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8]]></property>
        <!-- 配置数据库连接用户名 -->
        <property name="connection.username">root</property>
        <!-- 配置数据库连接密码 -->
        <property name="connection.password">123456</property>
        <!-- 配置数据库方言 -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 配置数据库表生成策略 -->
        <!--<property name="hibernate.hbm2ddl.auto">update</property> -->
        <!-- 配置是否打印显示SQL语句 -->
        <property name="show_sql">true</property>
        <!-- 配置是否格式化显示SQL语句 -->
        <property name="format_sql">true</property>
        <!-- 配置hibernate是否自动提交事务 -->
        <!--<property name="hibernate.connection.autocommit">true</property> -->
        <!-- 配置实体类对应的映射文件 -->
        <mapping resource="com/great/entity/Class.hbm.xml"></mapping>
        <mapping resource="com/great/entity/Student.hbm.xml"></mapping>
        <mapping resource="com/great/entity1/Product.hbm.xml"></mapping>
        <mapping resource="com/great/entity1/Factory.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>

多对一单向关联:

Factory.java

package com.great.entity1;

public class Factory {
    // 厂商类
    // 厂商id
    private int fId;
    // 厂商名字
    private String fName;

    public int getfId() {
        return fId;
    }

    public void setfId(int fId) {
        this.fId = fId;
    }

    public String getfName() {
        return fName;
    }

    public void setfName(String fName) {
        this.fName = fName;
    }

}

Product.java

package com.great.entity1;

public class Product {
    // 多对一单向关联
    // 产品类
    // 产品id
    private int pId;
    // 产品名字
    private String pName;
    // 厂商
    private Factory factory;

    public int getpId() {
        return pId;
    }

    public void setpId(int pId) {
        this.pId = pId;
    }

    public String getpName() {
        return pName;
    }

    public void setpName(String pName) {
        this.pName = pName;
    }

    public Factory getFactory() {
        return factory;
    }

    public void setFactory(Factory factory) {
        this.factory = factory;
    }

}

Factory.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping  package="com.great.entity1">
<class name="Factory" table="factory">
    <!-- 配置主键映射关系 -->
    <id name="fId" column="fId" type="int">
      <!-- 配置主键生成策略 -->
      <generator class="identity">
      </generator>
    </id>
    <!-- 配置属性和表字段映射关系 -->
    <property name="fName" column="fName" type="string"></property>
  </class>
</hibernate-mapping>

Product.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.great.entity1">
  <!-- 配置实体类与数据库表的映射关系 -->
  <class name="Product" table="Product">
    <!-- 配置主键映射关系 -->
    <id name="pId" column="pId" type="int">
      <!-- 配置主键生成策略 -->
      <generator class="identity">
      </generator>
    </id>
    <!-- 配置属性和表字段映射关系 -->
    <property name="pName" column="pName" type="string"></property>
    <!-- 多对一关联关系配置 -->
    <!-- many-to-one标签声明多对一关联关系,name指定多方所维护的一方的实例名 -->
    <many-to-one name="factory" class="com.great.entity1.Factory" cascade="save-update">
      <!-- column标签指定关联外键,还是子表的外键列名 -->
      <column name="fId"></column>
    </many-to-one>
  </class>
</hibernate-mapping>

TestManyToOneUnidirectional.java

package com.great.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.great.entity1.Product;

public class TestManyToOneUnidirectional {
    static Session session;

    // 多对一单向关联
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        // 加载hibernate主配置文件
        Configuration cfg = new Configuration().configure();
        // 构建session工厂
        SessionFactory sf = cfg.buildSessionFactory();
        // 打开session
        session = sf.openSession();
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        // 关闭session,释放资源
        session.close();
    }

    // 查询产品名字和厂家
    @Test
    public void testManyToOneSelect() {
        Product p = (Product) session.get(Product.class, 1);
        System.out.println("产品名字为:" + p.getpName());
        System.out.println("产品厂家为:" + p.getFactory().getfName());
    }
}

数据库:

factory:

product:

多对一双向关联:

Class.java

package com.great.entity;

import java.util.HashSet;
import java.util.Set;

import com.great.entity.Student;

public class Class {
    // 班级id
    private int cId;
    // 班级名字
    private String cName;
    // 注意点:必须new一个Set的实现类的实例
    // 原因:子表不一定有主表的关联数据,所以可能取出空集合,引发空指针异常
    private Set<Student> students = new HashSet<Student>();

    public int getcId() {
        return cId;
    }

    public void setcId(int cId) {
        this.cId = cId;
    }

    public String getcName() {
        return cName;
    }

    public void setcName(String cName) {
        this.cName = cName;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Class [cId=" + cId + ", cName=" + cName + ", students="
                + students + "]";
    }

}

Student.java

package com.great.entity;

import com.great.entity.Class;

public class Student {

    private int id;
    private String sName;
    // 多对一映射时,因为要维护一的一方的实例,所以外键不需要映射
    // private int cId;
    private Class classes;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getsName() {
        return sName;
    }

    public void setsName(String sName) {
        this.sName = sName;
    }

    public Class getClasses() {
        return classes;
    }

    public void setClasses(Class classes) {
        this.classes = classes;
    }

}

Class.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping  package="com.great.entity">
<class name="Class" table="class">
    <!-- 配置主键映射关系 -->
    <id name="cId" column="cId" type="int">
      <!-- 配置主键生成策略 -->
      <generator class="identity">
      </generator>
    </id>
    <!-- 配置属性和表字段映射关系 -->
    <property name="cName" column="cName" type="string"></property>
    <!-- 一对多关联关系配置 -->
    <!-- inverse属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方 -->
    <!-- fetch属性用来指定子表数据的抓取策略,默认值为"select",代表对主表子表进行单独查询 ,对主表子表单独发select语句-->
    <!-- fetch属性用来指定子表数据的抓取策略,设置为"join"时,代表对主表子表进行关联查询,对主表子表发出关联查询语句 -->
    <!-- lazy属性用来指定子表数据是否延迟加载,fetch="select"时起作用,fetch="join"时不起作用 -->
   <!--  fetch="select" lazy="true" -->
    <set name="students" cascade="all" inverse="true" >
      <!-- key配置的是子表的外键列名 -->
      <key column="cId"></key>
      <!-- one-to-many标签声明关联关系是一对多,class指定多方的实体类类型 -->
      <one-to-many class="com.great.entity.Student"/>
    </set>
  </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.great.entity">
    <!-- 配置实体类与数据库表的映射关系 -->
    <class name="Student" table="student">
        <!-- 配置主键映射关系 -->
        <id name="id" column="sId" type="int">
            <!-- 配置主键生成策略 -->
            <generator class="identity">
            </generator>
        </id>
        <!-- 配置属性和表字段映射关系 -->
        <property name="sName" column="sName" type="string"></property>
        <!-- 多对一关联关系配置 -->
        <!-- many-to-one标签声明多对一关联关系,name指定多方所维护的一方的实例名 -->
        <many-to-one name="classes" class="com.great.entity.Class"
            cascade="save-update">
            <!-- column标签指定关联外键,还是子表的外键列名 -->
            <column name="cId"></column>
        </many-to-one>
    </class>
</hibernate-mapping>

数据库:

class:

student:

时间: 2024-08-25 20:30:05

hibernate多对一关联映射两种形式的理解的相关文章

hibernate多对一关联映射

hibernate多对一关联映射: 实体类 (POJO) public class Student{ private int stuId; private String stuNum; private String stuName; private ClassRoom cr; } public class ClassRoom{ private int claId; private String claName; } 映射文件 <class name=" Student" tabl

一口一口吃掉Hibernate(六)——多对多关联映射

今天来说说hibernate中的多对多关联映射,多对多关联映射涉及到单向映射和双向映射2种. 首先举个多对多关联例子:用户User和角色Role,一个用户可以属于多个角色,一个角色可以有多个用户.这就是典型的多对多关联的例子.而单向关联映射则是只能由A端去操作B端,B端不能操作A端的数据.而双向关联映射则是A,B两端都可以操作另一端的数据. 先说单向关联映射,实体类如下: <span style="font-size:18px">/** * 学生类 * @author Lo

【SSH系列】Hibernate映射 -- 多对多关联映射

     映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张表中做一个关联,用第三张表来解决可能造成的数据冗余问题.今天这篇博文小编来简单的介绍一下hibernate中的多对多关联映射. 在某些系统中,一个用户可以有多个角色,一个角色也可以有多个用户,so,她们之间的关系就是多对多,多对多关联

【Hibernate步步为营】--关联映射之多对一

上篇文章讨论了Hibernate的基本映射,一个实体类对应着一张表,在相应的Hibernate Mapping文件中使用<class>标签映射.并且实体类中的普通属性对应着表字段,使用<property>标签映射.另外在构造实体类时应注意:在实体类中应实现无参的默认的构造函数,提供一个标示,建议不要使用final修饰实体类,为实体类生成getter和setter方法,最后介绍了几种主要的主键生成策略,接下来讨论多对一映射. 一.关联映射之多对一 对于多对一关联映射其实很容易理解,在

Hibernate ManyToOne Mappings 多对一关联映射

Hibernate框架的使用步骤: 1.创建Hibernate的配置文件(hibernate.cfg.xml) 2.创建持久化类,即其实例需要保存到数据库中的类(Employee.java) 3.创建对象-关系映射文件(Employee.hbm.xml) 4.通过Hibernate API编写访问数据库的代码 例子:多个员工对应一个地址. 一.创建hibernate.cfg.xml 配置文件: 注意数据库名.用户名.密码是否填写正确. <?xml version="1.0" en

【SSH进阶之路】Hibernate映射——多对多关联映射(八)

上篇博文[SSH进阶之路]Hibernate映射--一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数据冗余的问题. 举例 一个用户(User)对多个角色(Role),一个角色对多个用户. 分类 单向的多对多关联映射(单向User--->Role) 对象模型 关系模型 实例

hibernate之关于使用连接表实现多对一关联映射

[Hibernate]之关于使用连接表实现多对一关联映射 在我们项目使用中采用中间表最多的一般就是多对一,或者是多对多,当然一对一使用中间表也是可以的,但是这种几率通常少之又少!所以这里重点介绍多对一和一对多的采用中间表进行关联映射! 依然采用Group和Person来描述这个逻辑! Annotations配置 @Entity @Table(name="t_group") publicclass Group {     private Integer id;     private S

【Hibernate】——一对一关联映射

两个对象之间如果是一对一的关系,如Person-IdCard.在Hibernate中有两种策略可以实现一对一的关联映射: 主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系:数据库表不会有额外的字段来维护它们之间的关系,仅通过表得主键来关联. 唯一外键关联:外键关联,本来是用于多对一的配置,但是如果加上唯一的限制之后,也可以用来表示一对一关联关系: 而每种策略又分为两种方向的对应关系,即单向一对一关系和双向一对一关系.分类的原因一般是由需求决定的,单双向是站在不同的角度去看人

Hibernate一对一双向关联映射

关键原因在于对象模型具有方向性: 单向:一端只能加载另一端,不能反过来. 双向:两端都可以加载另一端. 问题来了:如何我们想从身份证端(IdCard)加载人(Person),怎么办呢? 下面我们开始介绍一对一的双向关联映射. 映射原理 双向关联映射与单向关联映射的原理是一样的,双向关联映射并不影响存储,只影响加载.所以,双向关联映射和单向关联映射的关系模型是一样的即数据库的表结构是一样的,只是IdCard的实体类和配置文件(IdCard.hbm.xml)发生了一点点变化. 对象模型 从上图中可以