映射:一对一(人与身份)和多对多(老师对学生)

一、一对一:

第一种情况:IdCard类的ID 既是主键又是外键

package dao.po;
//人
public class Person  {
    private int id; //ID
    private String name;//姓名
    private IdCard idCard; //身份证(对象)
}  
package dao.po;
//身份主类
public class IdCard{
    private int id;//ID
    private String address;//地址
    private Person person; //身份证的主人  
}  
<?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="dao.po">
    <class name="Person">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" not-null="true" length="255" column="`name`"/>
        <!-- 这里做一对一映射    -->
       <!-- 没什么好说的,就是一 one-to-one -->
       <one-to-one name="idCard" ></one-to-one> 
    </class>
</hibernate-mapping>  
<?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="dao.po">
    <class name="IdCard" table="id_card">
        <id name="id">
            <!-- 注意:  -->
            <!-- 本类的id 既是主键,又是外键  -->
          <!-- IdCard对象的是从对象, Person是主对象, 先有主,后有从.  -->
            <generator class="foreign">
                <!-- 此处的person是IdCard类的一个属性 -->
                <param name="property">person</param>
            </generator>
        </id>
        <property name="address" not-null="true" length="255" column="`address`"/>
        <!-- 此处的person是IdCard类的一个属性 -->
        <!-- constrained="true" 对生成的数据表产生约束,id_card表的id既是主键,又是外键 -->
        <!-- constrained="false" 表结构上没有约束, 取何值对对象关系没影响,只是对表结构有影响-->
        <one-to-one name="person" constrained="true"/>  
    </class>
</hibernate-mapping>  

  保存与查询:

package dao;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import dao.po.IdCard;
import dao.po.Person;
public class One2One{
    public static void main(final String[] args){
        add();
        final IdCard c1 = query(5);
        System.out.println(c1.getPerson().getName());
    }
    //保存
    public static void add(){
        final Person p1 = new Person();
        p1.setName("小明");
        final IdCard c1 = new IdCard();
        c1.setAddress("北京市海淀区上地");
        p1.setIdCard(c1); //建立关联(不能少)
       c1.setPerson(p1); //建立关联(不能少)  
        Session session = null;
        try{
            session = HibernateUtil.getSeesion();
            final Transaction tx = session.beginTransaction();
            //session.save(p1); //
            session.save(c1); //身份证是从对象依赖于主对象, "身份证"依赖于"人",
           //保存 c1 , 也会自动保存 他依赖的p1,前题是c1 与p1要关联 
            tx.commit();
            //SQL 如下:
            //Hibernate: insert into Person (`name`) values (?)
            //Hibernate: insert into id_card (`address`, id) values (?, ?)
            //虽然只执行了session.save(c1) , 但有两个insert 
        }finally{
            if (session != null){
                session.close();
            }
        }
    }
    //查询 身份证
    public static IdCard query(final int id){
        Session session = null;
        try{
            session = HibernateUtil.getSeesion();
            final IdCard c1 = (IdCard) session.get(IdCard.class, id);
            Hibernate.initialize(c1.getPerson());
            return c1;
            //SQL 如下:
            //Hibernate: select idcard0_.id as id3_0_, idcard0_.`address` as address2_3_0_ from id_card idcard0_ where idcard0_.id=?
            //Hibernate: select person0_.id as id2_1_, person0_.`name` as name2_2_1_, idcard1_.id as id3_0_, idcard1_.`address` as address2_3_0_ from Person person0_ left outer join id_card idcard1_ on person0_.id=idcard1_.id where person0_.id=?
            //注意person表又连了id-card表
        }finally{
            if (session != null){
                session.close();
            }
        }
    }
}  

第二种情况:IdCard类的ID 只是主键, IdCard类多对一属性 person_id做 外键,指向Person类的主键。

  这种情况有点像 多对一,关系如下图:

  两个配置文件内容如下

二、多对多:

  多对多由于在性能和操作都不大理想,所以使用很少。实际使用中最好转换为一对多的模型。Hibernate会为我们创建中间关联表,转换成两个一对多。

package dao.po;
import java.util.Set;
//学生类
public class Student{
    private int id;
    private String name;
    private Set<Teacher> teachers;
}  
package dao.po;
import java.util.Set;
//老师类
public class Teacher{
    private int id;
    private String name;
    private Set<Student> students;
}
<?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="dao.po">
    <class name="Student">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" not-null="true" length="255" column="`name`"/>
        <!-- name="teachers" 表示:Student类中有一个属性叫teachers (是Set集合)-->
        <!-- table="teacher_student" 表示:中间表表名叫teacher_student -->
        <set name="teachers" table="teacher_student">
            <!-- column="student_id" 表示:中间表teacher_student的字段-->
            <!-- Student类的id与中间表teacher_student的字段student_id对应-->
            <key column="student_id"/>
            <!-- column="teacher_id" 表示:中间表teacher_student的字段-->
            <!-- class="Teacher" 表示:中间表teacher_student的字段teacher_id与 Teacher类的id对应-->
            <many-to-many class="Teacher" column="teacher_id"/>
        </set>
    </class>
</hibernate-mapping>    
<?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="dao.po">
    <class name="Teacher">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" not-null="true" length="255" column="`name`"/>
        <set name="students" table="teacher_student">
            <key column="teacher_id"/>
            <many-to-many class="Student" column="student_id"/>
        </set>
    </class>
</hibernate-mapping> 

  保存操作:

package dao;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import dao.po.Student;
import dao.po.Teacher;
public class Many2Many {
    public static void main(final String[] args){
        add();
    }
    //添加几个老师与学生
    public static void add(){
        final Teacher t1 = new Teacher();
        t1.setName("语文老师");
        final Teacher t2 = new Teacher();
        t2.setName("数学老师");
        final Student s1 = new Student();
        s1.setName("学生小明");
        final Student s2 = new Student();
        s2.setName("学生小红");
        //final Set<Teacher> set_t = new HashSet<Teacher>();
        //set_t.add(t1);
        //set_t.add(t2);
        final Set<Student> set_s = new HashSet<Student>();
        set_s.add(s1);
        set_s.add(s2);
        //给老师set 学生
        t1.setStudents(set_s); //建立关联,只在一方面建立关联就行了, 不可给学生set()了老师,再老师set()了学生
        t2.setStudents(set_s); //建立关联,只在一方面建立关联就行了, 不可给学生建了关联,再老师建关联
        //给学生set老师,不可以再做
        Session session = null;
        try{
            session = HibernateUtil.getSeesion();
            final Transaction tx = session.beginTransaction();
            session.save(t1);
            session.save(t2);
            session.save(s1);
            session.save(s2);
            tx.commit();
        }finally{
            if (session != null){
                session.close();
            }
        }
    }
}
// 中间表teacher_student 表结构如下 :
//| teacher_student | CREATE TABLE `teacher_student` (
//  `teacher_id` int(11) NOT NULL,
//  `student_id` int(11) NOT NULL,
//  PRIMARY KEY  (`student_id`,`teacher_id`),
//  KEY `FK2E2EF2DE4BF3A147` (`teacher_id`),
//  KEY `FK2E2EF2DE3B5856A7` (`student_id`),
//  CONSTRAINT `FK2E2EF2DE3B5856A7` FOREIGN KEY (`student_id`) REFERENCES `student
//` (`id`),
//  CONSTRAINT `FK2E2EF2DE4BF3A147` FOREIGN KEY (`teacher_id`) REFERENCES `teacher
//` (`id`)
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 |  
时间: 2024-08-05 16:46:39

映射:一对一(人与身份)和多对多(老师对学生)的相关文章

mybatis入门基础(六)----高级映射(一对一,一对多,多对多)

一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: 1 CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname VARCHAR(32) NOT NULL COMMENT '商品名称', 4 price FLOAT(10,1) NOT NULL COMMENT '商品定价', 5 detail TEXT COMMENT '商品描述', 6 pic VARCHAR(64) DEFAULT NULL COMMENT

Mybatis学习总结(六)——高级映射(一对一,一对多,多对多)

一.订单商品数据模型 1.数据库执行脚本 创建数据库表代码: /*Table structure for table `t_user` */ CREATE TABLE t_user ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(32) NOT NULL COMMENT '用户名称', birthday DATE DEFAULT NULL COMMENT '生日', sex CHAR(1) DEFAULT NULL COMMENT '性别',

mybatis映射 一对一、一对多、多对多高级映射

1.数据库执行脚本 创建数据库表代码: 1 CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname VARCHAR(32) NOT NULL COMMENT '商品名称', 4 price FLOAT(10,1) NOT NULL COMMENT '商品定价', 5 detail TEXT COMMENT '商品描述', 6 pic VARCHAR(64) DEFAULT NULL COMMENT '商品图片', 7

mybatis3.2.7应用_高级映射(一对一、一对多、多对多)

1. 一对一查询 需求:查询订单信息,关联查询创建订单的用户信息 1.1 使用resultType实现 1.1.1 sql语句 确定查询的主表:订单表       确定查询的关联表:用户表      关联查询:使用外连接,还是内连接??   --由于orders表中有一个外键(user_id),通过外键关联查询用户表只能查询出一条记录,可以使用内连接 select t.*, u.username, u.sex, u.address from orders t, user u where t.us

Hibernate映射( 多对一、一对一、一对多、多对多)的配置方法

hihernate一对多关联映射(单向Classes----->Student) 一对多关联映射利用了多对一关联映射原理 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 也就是说一对多和多对一的映射策略是一样的,只是站的角度不同 在一一端维护关系的缺点: * 如果将t_student表里的classesid字段设置为非空,则无法保存 * 因为不是在student这一端维护关系,所以student

Mybatis(四) 高级映射,一对一,一对多,多对多映射

天气甚好,怎能不学习? 一.单向和双向 包括一对一,一对多,多对多这三种情况,但是每一种又分为单向和双向,在hibernate中我们就详细解析过这单向和双向是啥意思,在这里,在重复一遍,就拿一对多这种关系来讲,比如有员工和部门,一个部门中有多个员工,从部门方看,是一对多关系,而多名员工属于一个部门,是多对一关系,那么如果我们的业务需求只需要通过部门查找到所有的员工,那么我们就只需要进行单向一对多的映射,如果我们需要通过员工来查询出对应的部门,那么我们就需要进行单向多对一的映射,而如果我们这两个业

Hibernate映射关系:一对一、一对多和多对多

在 Hibernate 中,同样可以对多张存在关联关系的表进行操作,但需要在映射文件中,将对象的关联关系与数据库表的外键关联进行映射.本章将对 Hibernate 的关联关系映射进行详细讲解. 在关系型数据库中,多表之间存在着三种关联关系,分别为一对一.一对多和多对多,如图 1 所示 图 1  关系型数据库中多表之间的三种关联关系 这三种关联关系的具体说明如下. 一对一:在任意一方引入对方主键作为外键. 一对多:在“多”的一方,添加“一”的一方的主键作为外键. 多对多:产生中间关系表,引入两张表

java-mybaits-00502-案例-映射分析-一对一、一对多、多对多

1.一对一查询[类属性即可,association ] 案例:查询所有订单信息,关联查询下单用户信息. 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询.如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单. 1.1.方法一[resultType]: 使用resultType,定义订单信息po类,此po类中包括了订单信息和用户信息: 1.1.1.Sql语句: SELECT orders.*, user.username,

【SSH进阶之路】Hibernate映射——一对一双向关联映射(六)

上篇博文[SSH进阶之路]Hibernate映射--一对一单向关联映射(五),我们介绍了一对一的单向关联映射,单向是指只能从人(Person)这端加载身份证端(IdCard),但是反过来,不能从身份证端加载人得信息.如图所示: 关键原因在于对象模型具有方向性: 单向:一端只能加载另一端,不能反过来. 双向:两端都可以加载另一端. 问题来了:如何我们想从身份证端(IdCard)加载人(Person),怎么办呢? 下面我们开始介绍一对一的双向关联映射. 映射原理 双向关联映射与单向关联映射的原理是一