• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
风吹花落泪如雨
博客园    首页    新随笔    联系   管理    订阅  订阅

Hibernate学习笔记整理(三)----- 关联关系映射关系

一、了解什么是一对多?

     一对多这种关系用的很多,但是很多人对此模糊不清,一对多不也就是多对一吗,多对多中特殊的一个不也就是一对多吗,为什么还分的那么清楚?并且还是什么单向和双向的那么麻烦,其实原因很简单,就是针对不同的情况和业务需求而产生的这种说法,

     例如:学生和班级

        单向一对多:一个班级对应多个学生。 也就是说,在某种业务情况下,我只需要知道从一个班级中知道有哪些学生,但是我不需要知道一个学生在哪个班级,这时候我就没必要写通过学生能查找到对应班级这个业务

        单向多对一:多个学生对应一个班级,可以通过每个学生查找到所在的班级名称,而不能从班级中查找到有哪些学生在里面,这就是从多到一的单面考虑,也就是说,当我们的业务需求只需要通过学生能找到对应班级,而不需要通过班级知道有哪些学生的时候,就可以写这样的单向多对一的关系映射

        双向一对多/双向多对一:这两个是一个意思,既然度双向了,说明不管从哪一方去找另一方,度可以找得到,也就无所谓一对多,还是多对一了。从这个学生和班级来讲,通过学生能知道他所在的班级,通过班级,能知道该班级下所有的学生。

      通过这个例子就知道了单向和双向是干嘛用的,就是根据不同的业务所规定的,如果你需要双向就写双向的映射关系,如果只需要从一方到另一方,那么就写自己所需要的,单向一对多或者单向多对一。

     

    所以我们接下要讲解的就是这三种,单向一对多、单向多对一、双向一对多。

二、单向多对一

      多个用户属于同一个组,多个学生属于同一个班级,多个学生属于同一个宿舍,等等,很多关系是这种多对一。因为上面是拿班级和学生来举测例子,那么所有的例子我度会用这个。为了方便和你们阅读。  

      多个学生属于同一个班级。单向多对一    

                  User和Classes类的关系图。

通过上面的图可以看到,单向多对一就是在多的一方中加入外键,通过该外键就能够找到对应的班级,因为不需要从一端的这方去管理这种关系,所以我们如果从班级这方来看,是不知道该班级下有哪些学生的。只能从多的一方也就是学生这边找到是哪个班级。

三、单向一对多

      说了单向多对一,现在来说说单向一对多,根据前面我们讲的,其实就是换了一个角度去想这个问题,学生和班级,现在站在班级这方去看,肯定是需要通过班级能知晓所有在这个班学习的同学的信息。 

 

四、多对多映射关系

  要保存多对多的关系,两张表是不够的,需要增加第三张表来表示这种关系,来看下面的数据库关系图。

          这个图意思就是用student_course这个中间表来保存student和course这两张表的关系,并且student_course是联合主键。同时也是外键,指向student的sid和Course的cid。

          有人肯定会觉得为什么还要用第三张表,不直接使用两个外键,你指向我,我指向你这样呢,这样会暴露出一个很大的问题,如果学过数据库就应该会知道,这样的两张表相互关联,那么这两张表的关系就固定在那里了,删哪个表就不能删,这个都是小事,当你在查询一个表中数据时,会造成死循环,你查了我,我又在查你,一直重复下去。那就GG了。

为什么需要设置联合主键和两个外键:

                student通过自己的主键在连接表中查询,因为是复合主键,所以查询到的记录有很多,而不是唯一的,这些记录中就记录了一个学生的所有课程,拿到这些记录后,由于连接表中的有course的外键,所以能够通过记录中的c_id,找到course表中对应的记录。反过来,course通过自己的主键在连接表中查询得到很多记录,由于连接表中也有student的外键,所以通过记录中的s_id也能找到student中对应的记录。所以,表的设计就是这样,需要联合主键,并且也都是外键,这些都是有用的。少一个就查不出对方了。

其他的就省略了,只写重要的代码。由于刚建立起来的关系,数据库中还没有任何数据,那么就添加初始数据了。这里会出现一个问题。如果把注释的这一行给放开的话,
报一个org.hibernate.exception.ConstraintViolationException错误,为什么会这样呢?其实从我们上面对数据库设计图的分析我们可以知道(只是那个分析是用查询来当例子,增加数据跟那个过程差不多),
在course的StudentSet中添加一个学生,这个过程是怎样的呢?因为要对StudentSet进行操作,那么就会找到连接表,添加一个学生,那么就会在连接表中,添加一条course的cid对应student的sid的记录,然后如果
你在用student.getCourseSet().add(course)的话,又往连接表中增加了一条一模一样的记录,这个时候肯定会报错啊,因为是联合主键,两条记录一样,怎么会插的进去呢。所以就会出现违反约束异常(违反主键约束)了。 Course course
= new Course(); course.setCname("化学"); Student student = new Student(); student.setSname("qqq"); course.getStudentSet().add(student); // student.getCourseSet().add(course); session.save(course); session.save(student);

 

五、单向一对一主键关联

     一对一关系看起来简单,其实也挺复杂的。其中关系就包含了四种,单向双向和主键关联外键关联。 什么意思呢,也就是包含了单向一对一主键关联、双向一对一主键关联,单向一对一外键关联,双向一对一外键关联, 这四种中,单双向就不用在说了把,就是看你业务需求来去设置是否是单双向,而外键关联也很简单,前面的一对多和多对多度是依靠外键关联关系来写的。那主键关联关系是怎么样的呢?其实跟外键关联差不多,唯一的区别就是,让一个类的主键当作外键使用来指向另一个关联类的主键,从而两个类的主键就达到了同步,也就是一致。你的主键是什么我的主键就是什么。如果这看不懂,那么就看下面的详细讲解的。

通过人和身份证这个一对一的例子来解释。

          实体类的属性

数据库关系图

    person中的id既是主键又是指向IdCard主键的外键。通过外键得特性,可以知道person的id和IdCard的主键id要相同,所以这才叫做主键关系。

六、双向一对一主键关联

 

 实体类属性

    这个图中双向箭头的意思是不管从那边查找,都能够找到对方,比如,person到Idcard:直接拿自己的主键值到对方表中查找主键值一样的,查找到了就将该记录放到自己的idCard属性中,就行了  idCard到person也是一样,拿主键值到对方表中查找主键值相同的。查找到了就将记录放到person属性变量中。

数据库关系图

 

 注意:主键关系的一对一的缺点:不知道你们发现了没有,在增加实验数据的时候,必须得先有Idcard,才能有person

 

 

七、单向一对一外键关联

    来看看数据库关系图(跟一对多的数据库关系模型一样)

 

实体类中属性

     因为是单向一对一,从Person到IdCard,所以Person中多一个能存放IdCard实例对象的属性

 

八、双向一对一外键关系

双向也很简单,只要改变两个地方,就在IdCard.java和IdCard.hbm.xml中加入这种映射关系就足够了。

      实体类图

 

 数据库关系图还是跟单向一对一外键关系一样

 

posted @ 2018-03-07 12:44  风吹花落泪如雨  阅读(142)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3