Hibernate中实体映射关系可分为如下几种:
- 单边一对一,双边一对一
- 单边一对多,单边多对一
- 双边一对多,双边多对一
- 单边多对多,双边多对多
- 主键相同的单双边一对一
注解
标注在类之前
@Entity:表示所标注的Java类是实体。
@Table:表示所标注的Java类所对应的数据库表,其中name属性对应表名。
标注在变量之前
@Id:表示对应的变量表示为主键。
@GeneratedValue:其中的strategy属性用于表示主键的生成策略,共包含四种GenerationType.AUTO(主键由程序控制),GenerationType.IDENTITY(主键由数据库自动生成,自动增长型),GenerationType.SEQUENCE(根据底层数据库的序列来生成主键,条件是数据库支持序列),GenerationType.TABLE(使用一个特定的数据库表格来保存主键)。
@JoinColumn:
@OneToOne:
- cascade:配置级联方式,有PERSIST、REMOVE、MERGE、REFRESH等几种取值,分别表示在保存、删除、修改、刷新对应的类时,会自动在数据库中保存、删除、修改、刷新属于它的对象,ALL则表示所有动作皆级联。
- mappedBy:在双向关联时,用于映射。
@OneToMany:cascade,mappedBy属性同上。
@ManyToOne:cascade,mappedBy属性同上。
@ManyToMany:mappedBy属性同上。
@PrimaryKeyJoinColumn:用于设置共同主键。
@JoinColumn:添加一个新列,name属性表示新列的名称。
@JoinTable:添加一个新表。
单边一对一,双边一对一
单边一对一:例如一个人只能拥有一个身份证。
@Entity @Table(name="t_person") public class Person { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private String id; @OneToOne(cascade={CascadeType.ALL}) @JoinColumn(name="person_id", unique=true) private IdCard idCard; } @Entity @Table(name="t_idcard") public class IdCard { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private String id; private String name; private String sex; }
双边一对一:例如一个丈夫只能拥有一个妻子,一个妻子也只能拥有一个丈夫。
@Entity public class Husband { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @OneToOne @JoinColumn(name="wifeId") private Wife wife; } @Entity public class Wife { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @OneToOne(mappedBy="wife") private Husband husband; }
单边一对多,单边多对一
单边一对多:例如一个班级有多个学生,班级类中包含了学生类的集合
@Entity @Table(name="t_class") public class Class { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY) @JoinColumn(name="classid") private Set<Student> students = new HashSet<Student>(); } @Entity @Table(name="t_student") public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; }
单边多对一:例如一个班级有多个学生,学生类中包含了班级类
@Entity @Table(name="t_class") public class Class { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; } @Entity @Table(name="t_student") public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER) @JoinColumn(name="classid") private Class class; }
双边一对多,双边多对一
例如一个班级有多个学生,班级类中包含了学生类的集合,学生类中包含了班级类。双边关系中,控制权一般交给多方,因此在@OneToMany无需配置数据库的外键列,而只配置了一个mappyedBy属性,意思是告诉Hibernate,要到多方的一类中的group属性中去找配置信息
@Entity @Table(name="t_class") public class Class { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @OneToMany(mappedBy="class") private Set<Student> students = new HashSet<Student>(); } @Entity @Table(name="t_student") public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER) @JoinColumn(name="classid") private Class class; }
单边多对多,双边多对多
单边多对多:一个老师有多个学生,一个学生也有多个老师,但教师类或学生类只有一个类中才包含另外一个类
@Entity public class Teacher { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @ManyToMany @JoinTable( name="t_s", joinColumns={@JoinColumn(name="teacher_id")}, inverseJoinColumns={@JoinColumn(name="student_id")} ) private Set<Student> students = new HashSet<Student>(); } @Entity public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; }
双边多对多:在单边多对多的基础上,在另外一个类中添加对应类的集合,并设置mappedBy属性
@Entity public class Teacher { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @ManyToMany @JoinTable( name="t_s", joinColumns={@JoinColumn(name="teacher_id")}, inverseJoinColumns={@JoinColumn(name="student_id")} ) private Set<Student> students = new HashSet<Student>(); } @Entity public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @ManyToMany(mappedBy="students") private Set<Teacher> teachers = new HashSet<Teacher>(); }
主键相同的单边一对一,双边一对一
单边一对一:若两个实体类是一对一关系,可以对两个实体类使用相同的主键。例如一个人有且仅有一个身份证,故可以设置为相同主键。此时若在Person类中设置了PrimaryKeyJoinColumn,则在IdCard类中无需设置主键增长策略
@Entity @Table(name="t_person") public class Person { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private String id; @OneToOne(cascade={CascadeType.ALL}) @PrimaryKeyJoinColumn private IdCard idCard; } @Entity @Table(name="t_idcard") public class IdCard { @Id private String id; private String name; private String sex; }
双边一对一:在两边均设置PrimaryKeyJoinColumn,并且在利用session.save时,需提前手动设置对方的类Id
@Entity public class Husband { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; @OneToOne @PrimaryKeyJoinColumn private Wife wife; } @Entity public class Wife { @Id private int id; private String name; @OneToOne @PrimaryKeyJoinColumn private Husband husband; }