JPA(4)表表关联关系

在我们做数据库设计的时候,最烦的就是各种表之间的关联关系了,关联关系有:一对多,多对一,一对一,其中还有单向和双向的区别.

  1.双向一对多及多对一映射:既然是双向,那么就是同一类的了:双向一对多关系中,必须存在一个关系维护端,在 JPA 规范中,要求 many 的一方作为关系的维护端(owner side), one 的一方作为被维护端(inverse side)。 可以在 one 方指定 @OneToMany 注释并设置 mappedBy 属性,以指定它是这一关联中的被维护端,many 为维护端。 在 many 方指定 @ManyToOne 注释,并使用 @JoinColumn 指定外键名称,讲的比较难理解,下面是代码:

  

    @OrderBy("id")//指的是取出数据的时候,按照哪一个字段来进行排列,我们这里是按照user表的id字段排序,默认是ASC,完整用法:@OrderBy(value= "group_name ASC, name DESC")   
    @OneToMany(targetEntity=Phone.class,mappedBy="user")//mappedBy说的就是上面说的被维护端,多的那一端就是维护端,注意mappedBy="xxx" xxx表示的是在另外一个类中关联这个类的那个属性名,在这个例子中是user
    public Set<Phone> getPhones() {
        return phones;
    }

  @JoinColumn(name="user_id")//指定外键
    @ManyToOne(targetEntity=User.class)//
    public User getUser() {
        return user;
    }

顺带讲一下,单向多对一的怎么做,对于上面的代码来说,我们只要将User中将被维护的注解给去掉,当然Set<Phone>也需要去掉。

2.双向一对一映射:基于外键的 1-1 关联关系:在双向的一对一关联中,需要在关系被维护端(inverse side)中的 @OneToOne 注释中指定 mappedBy,以指定是这一关联中的被维护端。同时需要在关系维护端(owner side)建立外键列指向关系被维护端的主键列。
  

User.java:    @OneToOne(mappedBy="user")//因为需要指定其中一方为被维护段,我们设置user为被维护段
    public FirstLover getFirstLover() {
        return firstLover;
    }
    FirstLover.java:
        //使用OneToOne进行一对一的映射,name表示的是关联关系表的外键,注意的是,这个外键是被维护段的主键,所以是unqie的
    @JoinColumn(unique=true,name="user_id")
    @OneToOne
    public User getUser() {
        return user;
    }

在关联关系中,延迟加载经常是我们考虑的问题,可以使用在我们的这个例子中,可以使用:

    @JoinColumn(unique=true,name="user_id")
    @OneToOne(fetch=FetchType.LAZY)
    public User getUser() {
        return user;
    }

但是,有这样的情况:user可以不关联firstLover(因为外键是定义在FirstLover表中的),如果有 FirsetLover 关联就设置为代理对象而延迟加载, 如果不存在关联的 FirsetLover 就设置 null, Hibernate 在不读取 FirsetLover  表的情况是无法判断是否有关联有 FirsetLover , 因此无法判断设置 null 还是代理对象, 而统一设置为代理对象,也无法满足不关联的情况, 所以无法使用延迟加载,只 有显式读取 FirsetLover .

最后一种就是多对多的关联关系的情况,在双向多对多关系中,我们必须指定一个关系维护端(owner side),可以通过 @ManyToMany 注释中指定 mappedBy 属性来标识其为关系维护端。为了测试,我定义了两个类:

Student.java:
package com.hotusm.commom.entity;

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

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;

@Entity
public class Student {

    private Integer id;

    private String name;
    private String sex;

    private String school;
    private Set<Teacher> teachers=new HashSet<>();

    @GeneratedValue
    @Id
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getSchool() {
        return school;
    }
    public void setSchool(String school) {
        this.school = school;
    }

    @JoinTable(name="teach_stu",//指定中间表的表名,如果没有指定表名,那么默认的名字是:tab1_tab2
            joinColumns={@JoinColumn(name="teacher_id",//指定本类的主键在中间表的外键的字段名称,
            referencedColumnName="ID")},//指定本类的主键是什么,在这个例子中,teach_stu的teacher的id就是本类的主键值
            inverseJoinColumns={@JoinColumn(name="student_id",//和上面是一样的含义,指明另外一个类主键在中间表的名称
                referencedColumnName="ID" //指定另外一个类的主键是什么,这里都是ID
                    )}
            )
    @ManyToMany//加上多对多的标示
    public Set<Teacher> getTeachers() {
        return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }
    @Override
    public String toString() {
        return this.name;
    }
}
Teacher:
package com.hotusm.commom.entity;

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

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Teacher {

    private Integer id;

    private String name;

    private String subjectName;

    private Set<Student> students=new HashSet<>();

    @GeneratedValue
    @Id
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Column(name="SUBJECT_NAME")
    public String getSubjectName() {
        return subjectName;
    }
    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }

    @ManyToMany(mappedBy="teachers")//指定维护的一方,注意这里的名称是另外一个类的属性名: private Set<Teacher> teachers=new HashSet<>();
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
    @Override
    public String toString() {

        return this.name;
    }
}

基本上,关联关系也就几种了。

时间: 2024-12-12 00:27:51

JPA(4)表表关联关系的相关文章

jpa双向一对一关联关系

1.1.  关系维护方 Person.java package com.morris.entity; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persi

Hibernate+JPA(转)

近年来ORM(Object-Relational Mapping)对象关系映射,即实体对象和数据库表的映射)技术市场人声音鼎沸,异常热闹, Sun在充分吸收现有的优秀ORM框架设计思想的基础上,制定了新的JPA(Java Persistence API)规范.JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb3规范的一部分. 那么什么是JPA呢?JPA是通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期实体对象持久化到数据库中去.

Hibernate+JPA (EntityMange讲解)

近年来ORM(Object-Relational Mapping)对象关系映射,即实体对象和数据库表的映射)技术市场人声音鼎沸,异常热闹, Sun在充分吸收现有的优秀ORM框架设计思想的基础上,制定了新的JPA(Java Persistence API)规范.JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb3规范的一部分. 那么什么是JPA呢?JPA是通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期实体对象持久化到数据库中去.

Hibernate+JPA

参考链接:http://blog.163.com/hero_213/blog/static/398912142010312024809 近年来ORM(Object-Relational Mapping)对象关系映射,即实体对象和数据库表的映射)技术市场人声音鼎沸,异常热闹, Sun在充分吸收现有的优秀ORM框架设计思想的基础上,制定了新的JPA(Java Persistence API)规范.JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb3规范

jpa的双向一对多和双向一对一关联关系

在分享之前先给大家看两个异常,应该说这一类的异常还是很常见的,主要原因是jar包冲突 异常1: java.lang.NoSuchFieldError: INSTANCE at org.hibernate.type.BasicTypeRegistry.<init>(BasicTypeRegistry.java:94) at org.hibernate.type.TypeResolver.<init>(TypeResolver.java:59) at org.hibernate.cfg

JPA学习笔记(7)——映射多对一关联关系

多对一关联关系 两个实体类,User和Order,一个User可以有多个Order,一个Order只能有一个User 建立关联关系 使用@ManyToOne注解映射多对一关联关系 User实体类 package com.jpa.helloworld; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.pers

JPA学习笔记(8)——映射一对多关联关系

一对多关联关系 本文有很多和多对一是一样的,因此不会写得非常具体. 有看不懂的.能够參考JPA学习笔记(7)--映射多对一关联关系 Order实体类 package com.jpa.helloworld2; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; imp

JPA实体关联关系映射之概述

一.简介 首先来说关联关系是面向对象分析,面向对象设计最重要的部分,JPA是完全可以通过映射来简化数据持久化到数据,和Hibernate一样,JPA的关联关系也分为两种,一种是单向关联,一种是双向关联: 单向关联:只需要单向访问关联端,比如说:我们只能通过某一学期访问这学期的课程,而不能通过课程访问课程所属的学期,这种关联关系就是单向关联. 双向关联:关联的两端可以互相访问.比说说班级可以访问学生,学生也可以访问班级,这种关联关系就是双向关联. 关联关系可以分为如下几种: 单向:1-1:1-N;

JPA学习笔记(9)——映射双向一对一关联关系

双向一对一关联关系 一个部门有一个经理,一个经理管一个部门 Department实体类 package com.jpa.helloworld2; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; impo