什么是一对多,多对一?

  一对多,比如你去找一个父亲的所有孩子,孩子可能有两个,三个甚至四个孩子. 这就是一对多 父亲是1 孩子是多

    多对一,比如你到了两个孩子,它们都是有一个共同的父亲. 此时孩子就是多 父亲是1

  

 总结:

  •   一对多就是: 1找到n
  •   多对一就是: n找到1

有些人写概念写一大堆搞起我之前是一脸懵逼,还好弄懂了(手动滑稽)

双向多对一和双向一对多是不是同一个概念?

  是一个概念,双向多对一和双向一对多都是配置一个 一对多和多对一

什么是双向多对多?

  可以理解为n找n,如项目可以有很多人做,1个人可以做多个项目.

配置单向多对一

  通过上面我们可以了解,双向一对多是 1找n,因为区县有总有很多街道,虽然有的街道没有名字(滑稽),下面我将拿街道和区县举例,实体类的getset我就省略了

   //编号
    private Integer id;
    //街道名称
    private String name;
    //所属区县编号
    private Integer district_Id;
    //所属区县
    private District district;

因为要找所属区县,所以就增加了一个类类型的变量.

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "E:/codeIdea/hibernate_config/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
     <class name="cn.pojo.Street" table="street">
        <id name="id" column="id" type="java.lang.Integer">
            <!--设置主键自动增长就不多说了-->
            <generator class="increment"/>
        </id>
        <property name="name" type="string" column="name"/>
        <!--
            关联查询District类
            name是指Street类中的district属性
            column是指district表中外键
            class这个就不用多说了 District实体类的路径
            cascade的save-update表示 对街道进行添加或更新时会对 县区进行添加或更新
         -->
        <many-to-one name="district"
                     column="district_Id"
                     class="cn.pojo.District"
                     cascade="save-update"/>
    </class>
</hibernate-mapping>

我们来看下配置完后是否可以查询到区县

dao层

public Street findDistrct(Serializable id){
        return (Street)HibernateUtil.currentSession().get(Street.class,id);
    }

service层

  public Street getStreet(Integer id){
        Transaction tx=null;
        Street streets=null;
        try {
            tx=HibernateUtil.currentSession().beginTransaction();
            //获取持久对象 注意这里没 commit() 因为延迟加载的原因所以没有commit
            streets = street.findDistrct(id);
        } catch (HibernateException e) {
            e.printStackTrace();
            if(tx!=null)
                tx.rollback();
        }
        return streets;
    }

测试

StreetServiceImpl streetService = new StreetServiceImpl();
System.out.println(streetService.getStreet(1001).getDistrict().getName());

结果:

配置双向一对多

实体类属性 多了一个set因为是 1找n 所以是一个set因为set不允许重复值

    //编号
    private Integer id;
    //区县名称
    private String name;
    //街道
    private Set<Street> streetSet;

双向多对一就是在上面的基础上加了个一对多即成了双向,

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "E:/codeIdea/hibernate_config/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.pojo.District" table="district" schema="scott">
        <id name="id" column="id" type="java.lang.Integer">
            <!--设置自动增长不多讲了-->
            <generator class="increment"/>
        </id>
        <property name="name" type="string" column="name"/>
        <!--
            name同上
            inverse默认false  是否将对集合对象的修改反映到数据库中 false自己控制,true对方控制
            key 是street表中的外键
            class同上
        -->
        <set name="streetSet" inverse="true">
            <key column="district_Id"/>
            <one-to-many class="cn.pojo.Street"/>
        </set>
    </class>
</hibernate-mapping>

配置完1找n后我们再来查询下

dao层

public District getDistrct(Integer id){
        return (District)HibernateUtil.currentSession().get(District.class,id);
    }

service层

public Set<Street> findStreet(Integer id){
        Transaction tx=null;
        Set<Street> streets=null;
        try {
            tx=HibernateUtil.currentSession().beginTransaction();
            //得到持久状态的对象
            District distrct = distrctDao.getDistrct(id);
            //得到set
            streets=distrct.getStreetSet();
        } catch (HibernateException e) {
            e.printStackTrace();
            if(tx!=null)
                tx.rollback();
        }
        return streets;
    }

测试

DistrctServiceImpl ds = new DistrctServiceImpl();
Iterator<Street> streetIter = ds.findStreet(1004).iterator();
while (streetIter.hasNext()){
    System.out.println(streetIter.next().getName());
}

数据库的数据

结果

对双向一对读关联进行更新

dao 层

  public Street findDistrct(Serializable id){
        return (Street)HibernateUtil.currentSession().get(Street.class,id);
    }

service层 这里为了快点就没传参了 直接调用即可

public void updateStreet(){
    Transaction tx=null;
    try {
        //打开事务
        tx=HibernateUtil.currentSession().beginTransaction();
        //获得持久层对象
        Street streets = street.findDistrct(1000);
        //对区县进行修改
        streets.getDistrict().setName("京城");
        //提交事务
        tx.commit();
    } catch (HibernateException e) {
        e.printStackTrace();
        if(tx!=null)
            tx.rollback();
    }
}

我们来看看数据库没运行之前

运行之后 可以看到 知春路所属的区县改变了

双向多对多

  下面将用项目和员工之间的关系进行配置,因为项目表和员工表需要互相关联,如果两个表直接关联会导致数据有冗余,最重要的是因为相互关联会导致不能删除数据

可以看到这样关联是十分的不好的,这时候我们就可以找一个中间商,进行中转通过它可找到两个表的数据

注意中间商不用建实体类

项目实体类属性如下

    //编号
    private Integer empId;
    //员工名
    private String empName;
    //开发过的项目
    private Set<Project> projects;

项目配置

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "E:/codeIdea/hibernate_config/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="entity.Project" table="project">
        <id name="id" column="proid" type="java.lang.Integer">
            <generator class="assigned"/>
        </id>
        <property name="proName" type="string" column="proname"/>
        <!-- name是project中的属性名 cascade中的save-update表示 project中对employees集合的更改,添加会保存到数据库-->
        <set name="employees" table="proemp" cascade="save-update">
            <!--  project所关联的外键-->
            <key column="rproId"/>
            <!-- column是Employee表关联的外键-->
            <many-to-many class="entity.Employee" column="rempId"/>
        </set>
    </class>
</hibernate-mapping>

员工实体类属性

//编号
private Integer id;
//项目名称
private String proName;
//工作人员
private Set<Employee> employees;

员工配置

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "E:/codeIdea/hibernate_config/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="entity.Employee" table="employee">
        <id name="empId" column="empId" type="java.lang.Integer">
            <generator class="increment"/>
        </id>
        <property name="empName" column="empname"/>
        <!-- name是project中的属性名 inverse true表示将控制权给予别人 默认false-->
        <set name="projects" table="proemp" inverse="true">
            <!--Employee关联的外键-->
            <key column="rempId"/>
            <!--  column是project表所关联的外键-->
            <many-to-many class="entity.Project" column="rproId"/>
        </set>
    </class>
</hibernate-mapping>

配置完了进行添加如下

dao层

    public void add(Project project){
        HibernateUtil.currentSession().save(project);
    }

service层

public void add(Project project){
    Transaction tx=null;
    try {
        //打开事务
        tx=HibernateUtil.currentSession().beginTransaction();
        //保存
        empDao.add(project);
        //提交
        tx.commit();
    } catch (HibernateException e) {
        e.printStackTrace();
        if (tx!=null)
            //回滚
            tx.rollback();
    }
}

测试

//创建项目
Project project = new Project(3,"项目3");
//创建员工
Employee employee = new Employee();
Set<Employee> employees = new HashSet<>();
employees.add(employee);
employee.setEmpName("王麻子");
//添加员工 到项目中
project.setEmployees(employees);
//添加项目 保存到数据库
empSerivce.add(project);

没添加之前

运行后

因为控制权给了项目,在员工中进行如上操作对数据库中的项目表并不会进行改动,但是可以查询到如下

dao层

public Employee get(Serializable id){
    return (Employee)HibernateUtil.currentSession().get(Employee.class,id);
}

service层

EmpDao empDao =new EmpDao();
    public Employee get(Integer id){
        Transaction tx = null;
        Employee emp = null;
        try {
            //打开事务
            tx=HibernateUtil.currentSession().beginTransaction();
            //获取持久化对象
            emp = empDao.get(id);
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return emp;
    }

测试

EmpSerivce empSerivce = new EmpSerivce();
        Employee emp = empSerivce.get(1);
        //员工名
        System.out.println(emp.getEmpName());
        //迭代器
        Iterator<Project> iterable = emp.getProjects().iterator();
        //遍历 做过的项目
        while (iterable.hasNext()){
            System.out.println(iterable.next().getProName());
        }

结果

工具类代码如下:

    package tool;

    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;

    public class HibernateUtil {
        private static Configuration configuration;
        private static SessionFactory sessionFactory;
        //初始化配置和session
        static {
            try {
                //读取配置文件
                try {
                    configuration = new Configuration().configure();
                    //获取session对象
                    sessionFactory =configuration.buildSessionFactory();
                } catch (HibernateException e) {
                    e.printStackTrace();
                }
            } catch (HibernateException e) {
                throw new ExceptionInInitializerError();
            }
        }
        private HibernateUtil(){}
        //获取session对象
        public static Session currentSession(){
            return sessionFactory.getCurrentSession();
        }
    }

hibernate中配置单向多对一关联,和双向一对多,双向多对多的更多相关文章

  1. Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o

    Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o 1. Criteria,,Criterion ,, 1 <2. 主要的对象黑头配置磊 ...

  2. 【Hibernate框架】关联映射(一对多,多对一)

    根据我们的总结计划,上篇文章我们总结了有关于一对一映射相关知识,接下来,我们进行下一个阶段,一对多.多对一映射相关知识. 场景设定: 国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工.我们 ...

  3. Hibernate 中配置属性详解(hibernate.properties)

    Hibernate能在各种不同环境下工作而设计的, 因此存在着大量的配置参数.多数配置参数都 有比较直观的默认值, 并有随 Hibernate一同分发的配置样例hibernate.properties ...

  4. Hibernate框架--关联映射,一对多,多对多 inverse cascade

    回顾Hibernate: 1. hibernate开发环境搭建 ----> 引入jar: hibernate.jar + required + jpa + 驱动包 ---> hiberna ...

  5. Hibernate系列学习之(二) 多对一、一对一、一对多、多对多的配置方法

    这是近期做案件录入.java项目中体会的几点:项目理解很是深刻,和大家共勉! hihernate一对多关联映射(单向Classes----->Student) 一对多关联映射利用了多对一关联映射 ...

  6. 【转】Hibernate系列学习之(二) 多对一、一对一、一对多、多对多的配置方法

    hihernate一对多关联映射(单向Classes----->Student) 一对多关联映射利用了多对一关联映射原理 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向 ...

  7. 在Hibernate中配置Hilo进行数据绑定测试时出错:org.hibernate.MappingException: Could not instantiate id generator

    在进行学习具体类单表继承时使用hilo类型时总是在调度过程中提示如下信息,无法通过.留下记录备查. 在网上找相关信息, 未解决,详细如下: org.hibernate.MappingException ...

  8. 详解在Hibernate中配置数据库方言的作用和好处以及各种数据库的方言连接

    Hibernate底层依然使用SQL语句来执行数据库操作,虽然所有关系型数据库都支持使用标准SQL语句,但所有数据库都对标准SQL进行了一些扩展,所以在语法细节上存在一些差异,因此Hibernate需 ...

  9. Hibernate 配置双向多对多关联

    本文解决问题:Hibernate 中配置项目(Project) 员工(Employee)   双向多对多关联 方案一:直接配置双向多对多 方案二:配置第三个关联类(xml)   将多对多查分开来(形成 ...

随机推荐

  1. 【转载】win7mysql5.7.18免安装配置教程

    闲着没事,装个mysql试试,小编以前都是用的linux,感觉mysql安装就是傻瓜式操作啊,第一次在windows系统上装,感觉出了很多问题,现在将整个过程分享给大家,希望大家在安装的时候少走弯路. ...

  2. The nineteenth day

    Twinkle,twinkle,little start! 闪烁,闪烁,小星星 How I wonder what you are, 我想知道你是什么 Up above the world so hi ...

  3. Python进阶篇四:Python文件和流

    摘要: Python对于文件和流的操作与其他编程语言基本差不多,甚至语句上比其他语言更为简洁.文件和流函数针对的对象除了这两者之外还有,类文件(file-like),即python中只支持读却不支持写 ...

  4. win7上装红米4手机驱动提示空间不足

    首先说:小米的垃圾支持.我在支持页面上看着 miuiV4或V5版本,再看我手机上9.5的版本.就感觉有些不妙. 下载下来后,点击安装程序,提示我安装空间不足......我F盘可用空间140G,不够你造 ...

  5. android launcher

    1.android_launcher的源码详细分析 2.android---launcher 3.Android 4.4 Launcher3桌面源码分析 4.通过深度剖析Android之Launche ...

  6. BIEE入门(三)业务模型层

    正如它的名字所示(Business Model and Mapping Layer),业务逻辑层需要把物理层的数据源以一种业务用户的视角来重新组织物理层的各个数据源(所谓的Mapping),同时在业务 ...

  7. winform DataGridView 通用初始化

    void DGV_Init() { //名称 类型 设备数 累计转发次数 累计转发数据数 状态 ; i < ; i++) { DataGridViewTextBoxColumn dc = new ...

  8. 关于Oracle RAC节点间免密码策略

    在RAC安装过程中无论grid或是Oracle软件都需要配置节点间免密码策略.配置方法网上有很多,oracle和可以帮你配置,此处不多说. 但是在RAC运行过程中是不需要免密码登陆的,所以在集群安装完 ...

  9. submit text3 常用快捷键

    Ctrl+D : 选择单词,重复可增加选择下一个相同的单词 Ctrl+F : 查找内容 Ctrl+G : 跳转到指定行 Ctrl+H : 替换 Ctrl+J : 合并行(已选择需要合并的多行时) Ct ...

  10. Linux下apt-get的软件一般安装路径

    apt-get安装目录和安装路径:apt-get 下载后,软件所在路径是:/var/cache/apt/archivesubuntu 默认的PATH为PATH=/home/brightman/bin: ...