精华内容
下载资源
问答
  • 一Ø 一一是将数据表“垂直切分”,其实是不常见,或不常用的。也就是 A 表的一条记录对应 B 表的一条记录,为什么要这样的设计呢,不是增加了程度的复杂性吗,然而并不一定,举例说明: 1) 一个系统...
    
    

     一对一

    Ø  一对一是将数据表“垂直切分”,其实是不常见,或不常用的。也就是 A 表的一条记录对应 B 表的一条记录,为什么要这样的设计呢,不是增加了程度的复杂性吗,然而并不一定,举例说明:

     

    1)   一个系统必然有 Employee(员工表)(包含字段:EmployeeId、姓名、性别、年龄、电话、地址等),每个员工都为一个用户,所以还有张User 表(包含字段:UserId(关联 EmployeeId)、用户名、密码、角色等),这样你会发现,整合为一张表是否不太妥当?因为,User 的记录只会在登录时用到,感觉有点违背三大范式中的“确保每列都和主键列直接关联,而不是间接关联”。

     

    2)   还有种情况,这就要根据具体的业务来决定了。如果,当一张表的字段过于太多,而很多字段可能只有在某些情况下,才会使用到,这时也可以考虑使用一对一设计。

     

    Ø  优点

    1.   便于管理、可提高一定的查询速度

    2.   减轻 CPU  IO 读写,提高存取效率。

    3.   符合数据库设计的三大范式。

    4.   符合关系性数据库的特性。

     

    Ø  缺点

    1.   增加一定的复杂程度,程序中的读写难度加大。

    一对多

    Ø  一对多,是最常见的一种设计。就是 A 表的一条记录,对应 B 表的多条记录,且 的主键作为 B 表的外键。这主要看以哪张表为中心,以上示例以表为中心,就是一对多,如果以 B 表为中心,则是多对一。举几个例子:

    1.   班级表 与 学生表,一个班级对应多个学生,或者多个学生对应一个班级。

    2.   角色表 与 用户表,一个角色对应多个用户,或者多个用户对应一个角色。

    3.   商品表 与 图片表,一个商品对应多张图片,或者多张图片对应一个商品。

    多对多关系,需要创建一个表,表中需要两个字段,分别是引用,两个多对多字段主键的外键。
         例如:
    学生表(学号,姓名,…………)主键:学号
    课程表(课程号,课程名,…………)主键:课程号
    一个学生能选多门课,一个课可以由多个学生选,即是多对多关系,
    那么成绩表就是它们之间关系的体,
    即引用成绩表(学号,课程号,成绩)。这里学号和课程号,分别是学生表和课程表中学号和课程号的外键

    mysql表的一对一/一对多/多对多联系

    1.数据库中的多对多关联关系一般需采用中间表的方式处理,将多对多转化为两个一对多。

    2.通过表的关系,来帮助我们怎样建表,建几张表。

    一对一
    一张表的一条记录一定只能与另外一张表的一条记录进行对应,反之亦然。

    学生表:姓名,性别,年龄,身高,体重,籍贯,家庭住址,紧急联系人
    其中姓名、性别、年龄、身高,体重属于常用数据,但是籍贯、住址和联系人为不常用数据
    如果每次查询都是查询所有数据,不常用的数据就会影响效率,实际又不用
    常用信息表:ID(P),姓名,性别,年龄,身高,体重
    不常用信息表:ID(P),籍贯,家庭住址,紧急联系人

    解决方案:将常用的和不常用的信息分享存储,分成两张表
    不常用信息表和常用信息表,保证不常用信息表与常用信息表能够对应上:找一个具有唯一性的字段来共同连接两张表。
    一个常用表中的一条记录永远只能在一张不常用表中匹配一条记录,反之亦然。
    一对多
    一张表中有一条记录可以对应另外一张表中的多条记录;但是反过来,另外一张表的一条记录只能对应第一张表的一条记录,这种关系就是一对多或多对一。

    母亲与孩子的关系:母亲,孩子两个实体
    母亲表:M_ID(P),名字,年龄,性别
    孩子表:C_ID(P),名字,年龄,性别
    以上关系:一个妈妈可以在孩子表中找到多条记录(也可能是一条),但是一个孩子只能找到一个妈妈,是一种典型的一对多的关系。
    但是以上设计:解决了实体的设计表问题,但是没有解决关系问题,孩子找不到母亲,母亲也找不到孩子

    解决方案:在某一张表中增加一个字段,能够找到另外一张表中的记录:在孩子表中增加一个字段指向母亲表,因为孩子表的记录只能匹配到一条母亲表的记录。
    母亲表:M_ID(P),名字,年龄,性别
    孩子表:C_ID(P),名字,年龄,性别,母亲表ID(母亲表主键,孩子表外键)
    多对多
    一对表中(A)的一条记录能够对应另外一张表(B)中的多条记录;同时B表中的一条记录也能对应A表中的多条记录

    老师和学生
    老师表 T_ID(P),姓名,性别
    学生表 S_ID(P),姓名,性别
    以上设计方案:实现了实体的设计,但是没有维护实体的关系
    一个老师教过多个学生,一个学生也被多个老师教过

    解决方案:增加一张中间关系表
    老师与学生的关系表:ID(P),T_ID,S_ID 
    老师表与中间表形成一对多的关系,而中间表是多表;维护了能够唯一找到一表的关系;
    同样的学生表与中间表也是一个一对多的关系; 
    学生找老师:找出学生ID--->中间表寻找匹配记录(多条)--->老师表匹配(一条)
    老师找学生:找出老师ID--->中间表寻找匹配记录(多条)--->学生表匹配(一条)


    展开全文
  • 数据库多关系建表

    千次阅读 2019-08-26 00:45:59
    对于多多的关系,建表的方式是有两种的,最常见的做法就是建立一张中间关系表b,关联另外两张表a和c的主键,不要其他多余信息,这种做法通常的情况就是a表和c表中的数据不能有重复的,所以我们只能建立单独的关联...

    对于多对多的关系,建表的方式是有两种的,最常见的做法就是建立一张中间关系表b,关联另外两张表a和c的主键,不要其他多余信息,这种做法通常的情况就是a表和c表中的数据不能有重复的,所以我们只能建立单独的关联关系来关联两张表中的记录。而且建立这种关联关系时不会产生其他很多附属关联信息,或者说是a表和c表都需要独立的维护,不能受对应关系的影响。比如有一张用户表,和兴趣表,用户和兴趣之间属于多对多的关系,且用户表和兴趣表都是独立维护的,不能受关系变化而影响,所以只能建立关联关系表,这和业务有很大的关系。另外还有一种业务场景,比如团队和队员这种关系,业务场景是队员在不同团队中时,会有不同的其他属性,比如在a团队中是管理者,在b团队中是普通队员,这个时候,你会发现对应关系对应着很多属性,或者说团队表和队员表,其中队员表中的队员无法复用,同一个人必须重复出现,因为当队员处于不同团队时,他会有不同的属性,这个时候,关联关系表就没有必要存在了,因为队员表中一条队员记录只能对应一个团队,要对应其他团队,只能新增队员记录,其实这时队员表就已经是队员表和关系表的合体了,所以就不需要关联表了。这个时候多对多的关系就只涉及了两张表了,和前一个例子是完全不同的。所以建表时千万要分析清楚业务场景,因为我是见过有人在第二种业务场景下还建立了关联关系表,并且还把附属字段添加到关系表中,并把团队id关联到队员表中,不仅违反了正常人的逻辑,还没有简化成2张表,成功的将简单问题复杂了很多。

    展开全文
  • Spring Data JPA 之 一一,一多,多关系映射

    万次阅读 多人点赞 2018-06-10 17:01:10
    JPA使用@OneToOne来标注一一的关系。 实体 People :用户。 实体 Address:家庭住址。 People 和 Address 是一一的关系。 这里用两种方式描述JPA的一关系。 一种是通过外键的方式(一个实体通过外键...

     

    一、@OneToOne关系映射

    JPA使用@OneToOne来标注一对一的关系。

    实体 People :用户。

    实体 Address:家庭住址。

    People 和 Address 是一对一的关系。

    这里用两种方式描述JPA的一对一关系。

    一种是通过外键的方式(一个实体通过外键关联到另一个实体的主键);

    另外一种是通过一张关联表来保存两个实体一对一的关系。

     

    1、通过外键的方式

    people 表(id,name,sex,birthday,address_id

    address 表(id,phone,zipcode,address)

     

    People.java

    1. @Entity
    2. public class People {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;//id
    7.     @Column(name = "name", nullable = true, length = 20)
    8.     private String name;//姓名
    9.     @Column(name = "sex", nullable = true, length = 1)
    10.     private String sex;//性别
    11.     @Column(name = "birthday", nullable = true)
    12.     private Timestamp birthday;//出生日期
    13.     @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端,当删除 people,会级联删除 address
    14.     @JoinColumn(name = "address_id", referencedColumnName = "id")//people中的address_id字段参考address表中的id字段
    15.     private Address address;//地址
    16. }

    关联的实体的主键一般是用来做外键的。但如果此时不想主键作为外键,则需要设置referencedColumnName属性。当然这里关联实体(Address)的主键 id 是用来做主键,所以这里第20行的 referencedColumnName = "id" 实际可以省略。

     

     

    Address.java

    1. @Entity
    2. public class Address {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;//id
    7.     @Column(name = "phone", nullable = true, length = 11)
    8.     private String phone;//手机
    9.     @Column(name = "zipcode", nullable = true, length = 6)
    10.     private String zipcode;//邮政编码
    11.     @Column(name = "address", nullable = true, length = 100)
    12.     private String address;//地址
    13.     //如果不需要根据Address级联查询People,可以注释掉
    14. //    @OneToOne(mappedBy = "address", cascade = {CascadeType.MERGE, CascadeType.REFRESH}, optional = false)
    15. //    private People people;
    16. }

     

    2、通过关联表的方式来保存一对一的关系。

    people 表(id,name,sex,birthday)

    address 表 (id,phone,zipcode,address)

    people_address (people_idaddress_id)

    只需要创建 People 和 Address 两个实体

     

    People.java

    1. @Entity
    2. public class People {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;//id
    7.     @Column(name = "name", nullable = true, length = 20)
    8.     private String name;//姓名
    9.     @Column(name = "sex", nullable = true, length = 1)
    10.     private String sex;//性别
    11.     @Column(name = "birthday", nullable = true)
    12.     private Timestamp birthday;//出生日期
    13.     @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端
    14.     @JoinTable(name = "people_address",
    15.             joinColumns = @JoinColumn(name="people_id"),
    16.             inverseJoinColumns = @JoinColumn(name = "address_id"))//通过关联表保存一对一的关系
    17.     private Address address;//地址
    18. }

     

    Address.java

    不变

     

    二、@OneToMany 和 @ManyToOne

    实体 Author:作者。

    实体 Article:文章。

    Author 和 Article 是一对多关系(双向)。那么在JPA中,如何表示一对多的双向关联呢?

    JPA使用@OneToMany和@ManyToOne来标识一对多的双向关联。一端(Author)使用@OneToMany,多端(Article)使用@ManyToOne。

    JPA规范中,一对多的双向关系由多端(Article)来维护。就是说多端(Article)为关系维护端,负责关系的增删改查。一端(Author)则为关系被维护端,不能维护关系。

    一端(Author)使用@OneToMany注释的mappedBy="author"属性表明Author是关系被维护端。

    多端(Article)使用@ManyToOne和@JoinColumn来注释属性 author,@ManyToOne表明Article是多端,@JoinColumn设置在article表中的关联字段(外键)。

     

    Author.java

    1. @Entity
    2. public class Author {
    3.     @Id // 主键
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
    5.     private Long id; //id
    6.     @NotEmpty(message = "姓名不能为空")
    7.     @Size(min=2, max=20)
    8.     @Column(nullable = false, length = 20)
    9.     private String name;//姓名
    10.     @OneToMany(mappedBy = "author",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
    11.     //级联保存、更新、删除、刷新;延迟加载。当删除用户,会级联删除该用户的所有文章
    12.     //拥有mappedBy注解的实体类为关系被维护端
    13.      //mappedBy="author"中的author是Article中的author属性
    14.     private List<Article> articleList;//文章列表
    15. }

     

    Article.java

    1. @Entity
    2. public class Article {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;
    7.     @NotEmpty(message = "标题不能为空")
    8.     @Size(min = 2, max = 50)
    9.     @Column(nullable = false, length = 50// 映射为字段,值不能为空
    10.     private String title;
    11.     @Lob  // 大对象,映射 MySQL 的 Long Text 类型
    12.     @Basic(fetch = FetchType.LAZY) // 懒加载
    13.     @NotEmpty(message = "内容不能为空")
    14.     @Size(min = 2)
    15.     @Column(nullable = false// 映射为字段,值不能为空
    16.     private String content;//文章全文内容
    17.     @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)//可选属性optional=false,表示author不能为空。删除文章,不影响用户
    18.     @JoinColumn(name="author_id")//设置在article表中的关联字段(外键)
    19.     private Author author;//所属作者
    20. }

     

    最终生成的表结构

    article 表(id,title,conten,author_id)

    author 表(id,name)

     

    三、多对多 @ManyToMany

    实体 User:用户。

    实体 Authority:权限。

    用户和权限是多对多的关系。一个用户可以有多个权限,一个权限也可以被很多用户拥有。

    JPA中使用@ManyToMany来注解多对多的关系,由一个关联表来维护。这个关联表的表名默认是:主表名+下划线+从表名。(主表是指关系维护端对应的表,从表指关系被维护端对应的表)。这个关联表只有两个外键字段,分别指向主表ID和从表ID。字段的名称默认为:主表名+下划线+主表中的主键列名,从表名+下划线+从表中的主键列名。

     

    需要注意的:

    1、多对多关系中一般不设置级联保存、级联删除、级联更新等操作。

    2、可以随意指定一方为关系维护端,在这个例子中,我指定 User 为关系维护端,所以生成的关联表名称为: user_authority,关联表的字段为:user_id 和 authority_id。

    3、多对多关系的绑定由关系维护端来完成,即由 User.setAuthorities(authorities) 来绑定多对多的关系。关系被维护端不能绑定关系,即Game不能绑定关系。

    4、多对多关系的解除由关系维护端来完成,即由Player.getGames().remove(game)来解除多对多的关系。关系被维护端不能解除关系,即Game不能解除关系。

    5、如果 User 和 Authority 已经绑定了多对多的关系,那么不能直接删除 Authority,需要由 User 解除关系后,才能删除 Authority。但是可以直接删除 User,因为 User 是关系维护端,删除 User 时,会先解除 User 和 Authority 的关系,再删除 Authority。

     

    User.java

    1. @Entity
    2. public class User {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     private Long id;
    6.     @NotEmpty(message = "账号不能为空")
    7.     @Size(min=3, max=20)
    8.     @Column(nullable = false, length = 20, unique = true)
    9.     private String username; // 用户账号,用户登录时的唯一标识
    10.     @NotEmpty(message = "密码不能为空")
    11.     @Size(max=100)
    12.     @Column(length = 100)
    13.     private String password; // 登录时密码
    14.     @ManyToMany
    15.     @JoinTable(name = "user_authority",joinColumns = @JoinColumn(name = "user_id"),
    16.     inverseJoinColumns = @JoinColumn(name = "authority_id"))
    17.     //1、关系维护端,负责多对多关系的绑定和解除
    18.     //2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(User)
    19.     //3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Authority)
    20.     //4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
    21.     //即表名为user_authority
    22.     //关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_id
    23.     //关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,即authority_id
    24.     //主表就是关系维护端对应的表,从表就是关系被维护端对应的表
    25.     private List<Authority> authorityList;
    26. }

    注意:如注释中所言,上面的第20-21行的@JoinTable可以省略,默认可以生成

     

    Authority.java

    1. @Entity
    2. public class Authority {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     private Integer id;
    6.     @Column(nullable = false)
    7.     private String name; //权限名
    8.     @ManyToMany(mappedBy = "authorityList")
    9.     private List<User> userList;
    10. }

     

    测试 添加

    1. @SpringBootTest
    2. @RunWith(SpringRunner.class)
    3. public class UserRepositoryTest {
    4.     @Autowired
    5.     private UserRepository userRepository;
    6.     @Autowired
    7.     private AuthorityRepository authorityRepository;
    8.     @Test
    9.     public void saveAuthority() {
    10.         Authority authority = new Authority();
    11.         authority.setId(1);
    12.         authority.setName("ROLE_ADMIN");
    13.         authorityRepository.save(authority);
    14.     }
    15.     @Test
    16.     public void saveUser() {
    17.         User user = new User();
    18.         user.setUsername("admin");
    19.         user.setPassword("123456");
    20.         Authority authority = authorityRepository.findById(1).get();
    21.         List<Authority> authorityList = new ArrayList<>();
    22.         authorityList.add(authority);
    23.         user.setAuthorList(authorityList);
    24.         userRepository.save(user);
    25.     }
    26. }

    先运行 saveAuthority 添加一条权限记录,

    然后运行 saveUser 添加一条用户记录,与此同时,user_authority 表中也自动插入了一条记录

     

    测试 删除

    删除用户

    1. @SpringBootTest
    2. @RunWith(SpringRunner.class)
    3. public class UserRepositoryTest {
    4.     @Autowired
    5.     private UserRepository userRepository;
    6.     @Test
    7.     public void deleteUser() {
    8.         userRepository.deleteById(1L);
    9.     }
    10. }

    user 表中删除一条记录,同时 user_authority 能够级联删除一条记录

     

     

    参考:http://www.cnblogs.com/luxh/archive/2012/05/30/2527123.html

     

     

    再次更新

    其中 @OneToMany  和 @ManyToOne 用得最多,这里再补充一下

     

    关于级联,一定要注意,要在关系的维护端,即 One 端。

    比如 作者和文章,作者是One,文章是Many;文章和评论,文章是One,评论是Many。

    cascade = CascadeType.ALL 只能写在 One 端,只有One端改变Many端,不准Many端改变One端。

    特别是删除,因为 ALL 里包括更新,删除。

    如果删除一条评论,就把文章删了,那算谁的。所以,在使用的时候要小心。一定要在 One 端使用。

    举例

    One 端

     

    Spring Data JPA 之 一对一,一对多,多对多 关系映射

     

    Many 端

     

    本文转自:Spring Data JPA 之 一对一,一对多,多对多 关系映射 | 言曌博客

    展开全文
  • Hibernate对象关系映射详解之“一多”关系映射 之前学习Hibernate框架的时候,这七大关系映射一直是云里雾里的,虽然可以仿照写出代码,但是不能独立编写出来。鉴于工作中这个知识点使用的几率还是非常大的,...

    Hibernate对象关系映射详解之“一对多关系映射


    之前学习Hibernate框架的时候,对这七大关系映射一直是云里雾里的,虽然可以仿照写出代码,但是不能独立编写出来。鉴于工作中这个知识点使用的几率还是非常大的,所以花了一点时间静下心来学习了一下,在这里写下一点学习笔记和大家交流。欢迎大家指点交流!(下面的笔记以及所有的示例都是使用注解)

    我理解的关联映射就是将关联关系映射到数据库里,在对象模型中就是对一个或多个对象的引用。

    七大关联映射有:单向一对一,单向一对多,单向多对一,单向多对多,双向一对一,双向一对多,双向多对多。

    在学习关联映射之前,先理解何为“单向”?何为“双向”?

    1、在使用注解实现关系映射时,只在其中一端进行配置则表示是单向关系映射,在两端同时进行配置则表示双向关系映射

    2、单向和双向的实质区别就是:哪一方负责维护该层关系。例如在单向关系中,配置的一端负责关系的维护,另外一端不负责;双向则是双方都要维护该层关系。加载负责维护关系的一端,系统会自动加载另一端。

     

    举一个生活中的例子理解双向和单向:

    情景假设:A 和 B 是两个人

    情景一)单向关系:

        如果仅仅只是A喜欢B,则这层“喜欢”的关系就只是由A负责维护(或者说只能由A来维护),B不会进行维护。因为A对象中“喜欢”的属性中有B,所以在加载A这个人的数据时,同时会加载出B的相关数据;但是加载B的数据时,不会加载出A的相关数据,因为B的“喜欢”属性中没有A,甚至是没有“喜欢”这个属性。

    情景二双向关系:

        如果A 喜欢 B,同时B也喜欢A,则这层“喜欢”的关系就是由两个人同时维护(或者说可以由两个人维护)。同理于上,因为双方的“喜欢”属性中都有对方,所以在加载任意一个人的数据时,会加载出另外一个人的数据。

     

    说明:主要还是看例子中对象所持有的属性对其的影响,不要把一对多和多对一的关系联系到“喜欢”上,重点在属性!!!哈哈


    分割线==========================分割线==========================分割线


    在这几种关联映射中,我觉得一对多这类关系映射最为复杂,所以在这里我先讲一对多这类(单向一对多,单向多对一,双向一对多)。有的人可能或疑惑,为什么没有双向多对一?其实在Hibernate中,一对多和多对一关系映射其实质是一样的,就是在“多“(一)的一端加对方的引用,指向“一”(多)的一端。不同的是,一对多是在“一”端加“多”端的集合,而多对一是在“多”端加“一”端的对象。所以双向的一对多和双向的多对一是一样的。

    (因为下面的讲解会用到注解,如果对注解还不太熟悉的朋友可以先看一下注解及其属性讲解:Hibernate 关系映射注解详解


    下面的例子使用的是学生和班级的关系

    1、单向多对一


     学生和班级的关系就是多对一

    1.1代码:

    Student(多端)

    @Entity
    @Table(name = "ORM_Student")
    public class Student implements Serializable {
    	private static final long serialVersionUID = 1L;
       @Id
    	@GeneratedValue(strategy = GenerationType.AUTO, generator = "ggs01")
    	@SequenceGenerator(name = "ggs01", initialValue = 1, allocationSize = 1)
    	private int id;// 学号
    	private String name;// 姓名
    	private String sex;// 性别
       @ManyToOne(cascade = { CascadeType.ALL })
    	@JoinColumn(name = "grade_id")
    	private Grade grade_id;// 班级号(将学生和班级设计成多对一的关系,测试单向多对一的关系情况)
         ……(省略setter、getter方法)
         ……(省略构造方法、toString方法)

    Grade(一端)

    <span style="font-size:18px;">@Entity
    @Table(name = "ORM_Grade")
    public class Grade implements Serializable {
    
    	private static final long serialVersionUID = 1L;
       @Id
    	private int id;// 班级编号
    	private String name;// 班级名称
         ……(省略setter、getter方法)
         ……(省略构造方法、toString方法)</span>


    1.2测试代码:

    1)插入数据,生成表

        <span style="white-space:pre">	</span>/*
    	 * 插入信息
    	 */
    	@Test
    	public void addGrade(){
    
    		//插入班级信息
           Grade grade1 = new Grade(0701, "七年级1班");
    		Grade grade2 = new Grade(0702, "七年级2班");
    
    		Session session = sf.openSession();
    		Transaction tx = session.beginTransaction();
    		session.save(grade1);
    		session.save(grade2);		
    		//插入学生信息
    		Student student1 = new Student("张三", "男",grade1);
    		Student student2 = new Student("李四", "男",grade1);
    		Student student3 = new Student("王五", "男",grade2);
    		session.save(student1);
    		session.save(student2);
    		session.save(student3);
    		tx.commit();
    	}

    运行结果:

    生成两张表 orm_studente orm_grade ,其中 ORM_Student 表中含有一个外键 grade_id 对应 ORM_Grade 的主键。


    (2)查询数据,比较加载内容

    <span style="white-space:pre">	</span>/*
    	 * 查询班级信息
    	 */
    	@Test
    	public void queryGrade(){
    		Session session = sf.openSession();
    		Query query = session.createQuery("from Grade");
    		List<Grade> list = query.list();
    		for(Grade g : list)
    			System.out.println(g);
    	}
    	/*
    	 * 查学生信息
    	 */
    	@Test
    	public void queryStudent(){
    		Session session = sf.openSession();
    		Query query = session.createQuery("from Student");
    		List<Student> list = query.list();
    		for(Student g : list)
    			System.out.println(g);
    		System.out.println("=========下面测试加载多端时加载出来的一端=========");
    		Grade g = list.get(0).getGrade_id();
    		System.out.println(g);
    	}
    运行结果:

    1 查询班级信息>加载一的一端,没有其他信息被加载

    Hibernate:

        select

            grade0_.id as id1_,

            grade0_.name as name1_

        from

            ORM_Grade grade0_

    Grade [id=449, name=七年级1]

    Grade [id=450, name=七年级2]


    2、 查学生信息>加载多的一端,一的一端也被加载

    Hibernate:

        select

            student0_.id as id0_,

            student0_.grade_id as grade4_0_,

            student0_.name as name0_,

            student0_.sex as sex0_

        from

            ORM_Student student0_

    Hibernate:

        select

            grade0_.id as id1_0_,

            grade0_.name as name1_0_

        from

            ORM_Grade grade0_

        where

            grade0_.id=?

    Hibernate:

        select

            grade0_.id as id1_0_,

            grade0_.name as name1_0_

        from

            ORM_Grade grade0_

        where

            grade0_.id=?

    Student [id=1, name=张三, sex=, grade_id=Grade [id=449, name=七年级1]]

    Student [id=2, name=李四, sex=, grade_id=Grade [id=449, name=七年级1]]

    Student [id=3, name=王五, sex=, grade_id=Grade [id=450, name=七年级2]]

    =========下面测试加载多端时加载出来的一端=========

    Grade [id=449, name=七年级1]


    比较结果:

    从上面两个运行结果来看,在加载“一”的一端时,没有其他信息被加载;在加载“多”的一端,一的一端也被加载,这也就印证了上面开头的总结:加载负责维护关系的一端,系统会自动加载另一端。


    2、单向一对多

    单向一对多单向多对一原理类似,就是只在“一”端添加“多”端对象的集合的引用(即在Grade对象中添加Set<Student>集合变量以及该变量的settergetter方法),并且在getter上添加注解:@OneToMany(cascade={CascadeType.ALL})


    测试代码和示例一的一样,只是运行的结果会不同:

    发送的SQL语句不一样:单向一对多,如果将维护关系设置在“一”端,在运行时会比示例一多发送n条update语句(n的值为“多”端的记录条数)。

    ② 数据加载不同:单向一对多在加载多端时,不会加载出其他数据,而在加载一端时,会加载出多端的数据。


    一般不使用单向一对多的原因:

    1、如果在“多”端将“一”端的外键设置为非空,在插入数据的时候会报错。

    报错原因:

    将关系设置在“一”端时,向“多”端插入数据的时候,因为没有“一”端的数据,所以此时一端对应的外键是null,如果将数据库中“多”端的外键设置为非空,此时就会报错。

            可以理解为,维护关系在“一”的一端,所以“多”的一端并不知道“一”的一端的存在,所以保存“多”的一端时,该数据表中“一”的一端的外键是空的。

    2、当维护关系在“一”的一端时,操作“一”端时会多发送n条update语句。当操作的记录较多时,会增加系统消耗。

    原因:

    在上面已经有提及到,当保存“多”端数据时,开始并没有“一”端的值(即外键值为null),记录保存完毕后,系统会通过update更新的方式向“多”端中添加外键值,所以此时又会发送一条update语句。



    3、双向一对多(不加mappedBy

    3.1代码:

    Student(多端):

    @Entity
    @Table(name = "ORM_Student")
    public class Student implements Serializable {
    	private static final long serialVersionUID = 1L;
       @Id
    	@GeneratedValue(strategy = GenerationType.AUTO, generator = "ggs01")
    	@SequenceGenerator(name = "ggs01", initialValue = 1, allocationSize = 1)
    	private int id;// 学号
    	private String name;// 姓名
    	private String sex;// 性别
       @ManyToOne(cascade = { CascadeType.ALL })
    	@JoinColumn(name = "grade_id")
    	private Grade grade_id;// 班级号(将学生和班级设计成多对一的关系,测试单向多对一的关系情况)
       ……(省略setter、getter方法)
       ……(省略构造方法、toString方法)

    Grade(一端):

    @Entity
    @Table(name = "ORM_Grade")
    public class Grade implements Serializable {
    
    	private static final long serialVersionUID = 1L;
       @Id
    	private int id;// 班级编号
    	private String name;// 班级名称
       @OneToMany(cascade={CascadeType.ALL})
    	@Column(name="student_id")
    	private Set<Student> students; //班级学生信息
       ……(省略setter、getter方法)
       ……(省略构造方法、toString方法)

    3.2测试代码:

    测试代码和示例1一样


    3.3运行结果:

    ① 不加mappedBy的话,会生成三张表,有一张中间表。生成中间表的原因和示例2中的类似,Student对应的表中有一个外键,同理于示例2,因为主键的唯一性,在Grade中不会存在Student的外键,所以会生成一张中间表。-->关于mappedBy属性的介绍,见上文要点

    ② 在数据的加载方面,与单向最大的不同就是双向关系,加载任意一端,都会自动加载出另一端的数据。

     

    4、双向一对多(加mappedBy

    该示例与示例3是一样的操作,不同的是需要在@OneToMany注解处加mappedBy属性。添加mappedBy属性后,不会生成第三张中间表。根据上述对生成第三张中间表的原因进行分析可以得到,主要是因为“一”的一端需要维护一对多的关系,也就是需要加载“多”的一端的数据,限于主键的唯一性,所以需要生成一张中间表(该表主要是为“一”端生成)。

    “一”端添加属性mappedBy后,就是意味着,将“一”端需要维护的关系转移到mappedBy所指定的对象(必须是“多”端配置的外键属性),相当于让“多”端帮忙打理这层关系,当加载“一”端时,按照双向关系的原理,是需要加载“多”端的,但是这时候并不是“一”端亲自去加载,而是通过“多”端协助加载。


    -->关于mappedBy属性的介绍,见 Hibernate 关系映射注解详解







    展开全文
  • 关系(一一,一多,多多)

    千次阅读 2018-03-03 21:04:31
    可以在数据库图表中的表之间创建关系,以显示一个表中的列与另一个表中的列是如何相链接的。在一个关系型数据库中,利用关系可以避免多余的数据。例如,如果设计一个可以跟踪图书信息的数据库,您需要创建一个名为 ...
  • 就数据库而言,实体往往指某类事物的集合。...实体之间的关系有 一一(如一个学生对应一个档案,一个档案对应一个学生); 一多,多一; 多多; 数据库中一一的实现方式: (1)唯一外键方式:在A和B任...
  • 1. 一一的表,两表的属性实际上完全可以合并成一个表,共用一个主键即可; 2. 一多的表,可以设中间关联表,也可以将关联表并入“多”这头;若设独立关联表,则可引入“多”这头的主键作为其主键,也可另立主键...
  • 一、关系数据结构及形式化定义 1、关系 关系模型的数据结构非常简单,只包含单一的数据结构——关系。在用户看来,关系模型中数据的逻辑结构是一张扁平的二维表。 1.1域 域是一组具有相同数据类型值的集合。 ...
  • 数据库中的数据表之间的关系包括一一,一多,多多,它们分别使用关键字OneToOneField,ForeignKey,ManyToManyFiled进行定义,之前已经写了一多,多多介绍以及使用,准备再找一个时间写一下它们之间的一个...
  • JPA中的映射关系 jpa中维护one to one ,one to many, many to one ,many to many 四种映射关系。  在每个关系中,双方中的一方在其表中拥有连接列。那么一方称为所有方(owning side) 或者关系的所有者。 不具有...
  • 关系数据库与非关系数据库的区别

    万次阅读 2018-11-01 20:50:59
    当前主流的关系型数据库有Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。 非关系型数据库有 NoSql、Cloudant。 nosql和关系型数据库比较? 优点: 1)成本:nosql数据库简单易部署,基本都是开源...
  • 关系关系是最普通的一种关系。在这种关系中,A 表中的一行可以匹配 B 表中的多行,...只有一个相关列是一个主键或具有唯一约束时,才能创建一关系。 多关系 在多关系中,A
  • 关系型和非关系型数据库的区别

    千次阅读 2018-11-19 16:57:56
    当前主流的关系型数据库有Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。 非关系型数据库有 NoSql、Cloudant。 nosql和关系型数据库比较? 优点: 1)成本:nosql数据库简单易部...
  • 关系(1)域(Domain)(2)笛卡尔积(Cartesian Product)(3)关系(Relation)(4)三类关系2.关系模式(1)什么是关系模式(2)定义关系模式3.关系模式和关系的对比4.关系数据库 0.思维导图 1. 关系 什么是...
  • 关系模式是对关系的描述(有哪些属性,各个属性之间的依赖关系如何),模式的一个具体值称为模式的一个实例。模式反应是数据的结构及其联系,是型,是相对稳定的,实例反应的是关系某一时刻的状态,是值,是相对变动...
  • 关系数据库系列文章之到底什么是关系(一)

    千次阅读 多人点赞 2018-08-05 02:28:45
    在语言X中如何实现Y,像这种具体的只是(know-how)可快速提高你的工作效率。但是一旦语言发生变化,这种知识就无法再使用。... 作为程序员,在日常的开发中,我们避免不了的就要接触数据库这个概念,而关系...
  • 数据库实体间多关系处理

    千次阅读 2013-04-14 10:30:38
    数据库实体间多关系处理   数据库实体间有三种对应关系:一一,一多,多多。 一关系示例:一个学生对应一个学生档案材料,或者每个人都有唯一的身份证编号。 一关系示例:一个学生只属于一个...
  • 通用的关系SRO用于描述许多不同类型的关系,而特定的Sighting SRO包含表示Sighting关系的其他属性。   为下面定义的每个SRO提供属性信息,关系信息和示例。 属性信息包括公用属性以及特定于每个SRO的属性。 ...
  • json序列化的对象中存在...使用@JsonBackReference标记在有多一或者多关系的属性上即可解决这个问题,举例: @JsonBackReference @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "market_id") privat
  • 关系的概念引入到数据库系统作为数据模型的数据结构时,既有所限定和也有所扩充。 关系的数学定义例: 课程={离散,C语言…..},学生={张三,李四…..} 笛卡儿积(cartesian product):设D1、…、Dn是n个域。D1、…...
  • 二元关系

    千次阅读 2015-04-24 20:33:26
    由两个元素x和y(允许x=y)按一定顺序排列成的二元组叫做一个有序或序偶,记作,y>,其中x是它的第一元素,y是它的第二元素。设A,B为集合,用A中元素为第一元素,B中元素为第二元素构成有序。所有这样的有序...
  • 关系模式分解

    千次阅读 2019-06-19 18:00:00
    无损分解:对关系模式分解时,原关系模式的任何一个合法的关系值在分解之后应该能通过自然连接运算恢复起来,这就是无损连接所要解决的问题。 例1: 设有关系模式R(ABC),分解成ρ={AB,AC}。 2.无损分解的测试...
  • nlp中的实体关系抽取方法总结

    万次阅读 多人点赞 2020-07-04 21:23:00
    基于模板匹配的关系分类构建简单、适用于小规模特定领域,但召回率低、可移植性差,遇到另一个领域的关系分类需要重新构建模板。 2、半监督学习 bootstrapping(自举):利用少量的实例作为初始种子集合,然后在...
  • 关系抽取常用方法

    万次阅读 2019-03-01 08:32:39
    关系抽取通常会基于以下几种方式去做: 基于规则 监督学习 半监督 &amp;amp;amp; 无监督学习 ...关系的实体(实体1,is - a,实体2) 比如我们有一些文章: &amp;quot; … apple is a fr...
  • 目录 集合中的三种关系 等价关系举例 相容关系举例 偏序关系举例 ...等价关系与等价类的例题 ...集合中的三种关系 ...序关系(偏序关系):设A是一个集合,若A上的关系R是自反的,反对称的,传递...
  • 集合及二元关系

    千次阅读 多人点赞 2019-06-06 15:47:28
    集合及关系 关系的运算 AxB:笛卡尔乘积。A中的元素作为第一元素,B中的元素作为第二元素,构成所有的序偶构成的集合作为结果。 domR:R的定义域。...F⚪G:GF的右合成。第一元素x来自F,第二元素y来自G...
  • 相关与因果关系

    千次阅读 2018-02-09 15:26:04
    相关表示两个变量之间存在关联,但并不是因果关系。《爱上统计学》一书给了一个例子:在美国中西部的一个小镇,地方警察局局长发现冰淇淋消费量越多,犯罪率就越高。这个例子中,冰淇淋消费量和犯罪率是正相关的,但...
  • 当前主流的关系型数据库有Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。 非关系型数据库有 NoSql、Cloudant。   ==========================优缺点分析如下================================...
  • 关系型数据库与非关系型数据库

    万次阅读 多人点赞 2018-04-18 15:45:07
    当前主流的关系型数据库有Oracle、DB2、Microsoft SQL Server、... 性能NoSQL是基于键值的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。 2. 可扩展性同样也是因为基...
  • 关系数据库规范化理论

    万次阅读 2018-03-01 22:54:50
    关系数据库规范化理论一个关系数据库由一组关系模式组成,一个关系由一组属性名组成,关系数据库设计就是如何把已给定的相互关联的一组属性名分组,并把每一组属性名组织成关系的问题。1、关系规范化的作用所谓规范...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,278,546
精华内容 911,418
关键字:

对当关系