@ManyToOne 注解定义了与另一个具有多对一多重性的实体类的单值关联。通常不需要明确指定目标实体类型,它可以从被引用的对象类型推断出来。例如:
// 下面的目标实体类型为 Custormer,不需要手动指定 @ManyToOne(optional=false) private Customer customer;
如果关系是双向的,则不具有所有权的 OneToMany 实体端必须使用 mappdBy 属性来指定作为关系所有者的实体的关系字段或属性。
实例1:假如我们拥有两个实体,分别是教师(Teacher)和学生(Student),Teacher 和 Student 是一对多关系(一个教师可以拥有多个学生)。那么在 JPA 中,如何表示一对多的双向关联呢?
JPA 使用 @OneToMany 和 @ManyToOne 注解来标识一对多的双向关联。One 端(Teacher)使用 @OneToMany 注解,Many 端(Student)使用 @ManyToOne 注解。
在 JPA 规范中,一对多的双向关系由多端(Student)来维护。就是说多端(Student)为关系维护端,负责关系的增删改查。一端(Teacher)则为关系被维护端,不能维护关系。
One 端(Teacher)的 @OneToMany 注解的 mappedBy="teacher" 属性表明 Teacher 是关系被维护端。
Many 端(Student)使用 @ManyToOne 和 @JoinColumn 注解来指定属性 TEACHER_ID 是 Student 表中的关联字段(外键)。
Teacher.java 类
@Data @Entity @Table public class Teacher { @Id @GeneratedValue private int id; @Column private String name; @OneToMany(mappedBy = "teacher") private List<Student> studentList; }
Student.java 类
@Data @Entity @Table public class Student { @Id @GeneratedValue private int id; @Column private String name; @ManyToOne @JoinColumn(name = "teacher_id") private Teacher teacher; }
CREATE TABLE `teacher` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `student` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `teacher_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `I_STUDENT_TEACHER` (`teacher_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ManyToOne 注解可以在可嵌入类内使用,以指定从可嵌入类到实体类的关系。如果关系是双向的,则不具有所有权的 OneToMany 实体端必须使用 OneToMany 注解的 mappdBy 元素来指定关系拥有端的可嵌入字段或属性的关系字段或属性。在 mappedBy 元素中必须使用点(“.”)符号语法来指示嵌入属性中的关系属性。与点符号一起使用的每个标识符的值是相应嵌入字段或属性的名称。
实例2:将学生中的 name 和关于 Teacher 的信息提取到单独的 StudentExt 嵌入类中,代码如下:
Teacher.java 类
@Data @Entity @Table public class Teacher { @Id @GeneratedValue private int id; @Column private String name; @OneToMany(mappedBy = "studentExt.teacher") private List<Student> studentList; }
Student.java 类
@Data @Entity @Table public class Student { @Id @GeneratedValue private int id; @Embedded private StudentExt studentExt; }
StudentExt.java
@Data @Embeddable public class StudentExt { @Column private String name; @ManyToOne @JoinColumn(name = "teacher_id") private Teacher teacher; }
CREATE TABLE `teacher` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `student` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `teacher_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `I_STUDENT_TEACHER` (`teacher_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ManyToOne 注解属性详情:
targetEntity:(可选)作为关联目标的实体类,默认为存储关联的字段或属性的类型。默认值 void.class
cascade:(可选)必须级联到关联目标的操作,默认情况下,不会级联任何操作。默认值 {}
fetch:(可选)关联是应该延迟加载还是必须立刻加载。立刻加载策略是持久性提供程序运行时的一个要求,即必须立刻获取关联的实体。懒惰策略是对持久性提供程序运行时的一个提示。默认值 javax.persistence.FetchType.EAGER
optional:(可选)关联是否为可选。如果设置为 false,则必须始终存在非空关系。默认为 true