配置实体之间的关系可以用xml和注解两种方式,现在整理一下基于注解的关联关系配置。以下基于Student和Teacher两个类来假设关系。
一、 一对一基于外键关联
1 单向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@OneToOne
@JoinColumn(name="tid",unique=true) ----->@JoinColum设置了外键的名称为tid(数据库字段名),如果不设置,则默认为另一类的属性名+ _id,即techer_id。外键的值是唯一的(unique),不可重复,与另一类的主键一致
private Teacher teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
}
//以上,Student单向关联Teacher,外键在student表中,维护关系当然也由Student来维护。
2 双向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@OneToOne(mappedBy="student") ---->需要加上mappedBy="student",如果不加上的话, student也会生成一个外键(techer_id),即两个表中都会有对方的外键,mappedby="student"需要指向与他关联对象的一个属性,说明双向关联关系中,有且仅有一端是作为主体(owner)端存在的,主体端负责维护联接列,对于不需要维护这种关系的从表则通过mappedBy属性进行声明,mappedBy的值指向主体的关联属性。
private Teacher teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
@OneToOne
private Student student;
}
//配置了双向关联,mappedBy指定teacher维护关系,外键在teacher表中。
//t.setStudent(s)
//session.save(t) 会维护关系
//s.setTeacher(t)
//session.save(s) 不会维护关系
二、多对一单向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@ManyToOne
@JoinColumn(name="tid") ----->@JoinColum设置了外键的名称为tid(数据库字段名),如果不设置,则默认为另一类的属性名+ _id,即techer_id。
private Teacher teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
}
三、一对多单向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@OneToMany ----->一对多注解@OneToMany(单向),如果只写@OneToMany的话,hibernate会建一张中间表来维护他们之间的关系,表中包含两个表的主键id
@JoinColumn(name="sid") ------>@JoinColumn(name="sid"),则不会建中间表,他会在多的一端加上外键sid,来维护他们之间的关
private List<Teacher> teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
}
四、一对多双向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@OneToMany(mappedBy="student") ----->不加mappedBy会创建中间表
@JoinColumn(name="sid") ------>@JoinColumn(name="sid"),如果指定了外键字段名称,则多的一端也需要指定相同的字段名称
private List<Teacher> teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
@ManyToOne
@JoinColumn(name=" sid") ///需要指定外键与一的一端给的外键名称一致,@JoinColumn(name=" roleid "),也可以不指定,如果在多的一端不指定,则一的一端也不能指定,否则为生成两个外键
private Student student;
}
五、多对多单向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@ManyToMany ---->多对多映射:注解@ManyToMany(单向),默认情况下,hibernate会自动的创建一张中间表来维护多对多关系
默认中间表的名称 :student_teacher中间表,字段的名称student_id teacher_id,如果想更换表名和字段名称,注解如下:
@JoinTable(name="s_t",joinColumns={@JoinColumn(name="s_id")},inverseJoinColumns={@JoinColumn(name="t_id")})
private List<Teacher> teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
}
六、多对多双向关联
@Entity
@Table(name="student")
public class Student{
@Id
@Column(name="id")
private String sid;
@Column
private String name;
@ManyToMany ---->多对多映射:注解@ManyToMany(单向),默认情况下,hibernate会自动的创建一张中间表来维护多对多关系
默认中间表的名称 :student_teacher中间表,字段的名称student_id teacher_id,如果想更换表名和字段名称,注解如下:
@JoinTable(name="s_t",joinColumns={@JoinColumn(name="s_id")},inverseJoinColumns={@JoinColumn(name="t_id")})
private List<Teacher> teacher;
}
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@Column(name="id")
private String tid;
@Column
private String name;
@ManyToMany(mappedBy="teacher")
private List<Student> student;
}
七 网上的一些总结
1 双向关联时,如果没有指定由谁来维护关联关系,则系统会给我们创建一张中间表。
2 通过hibernate来进行插入操作的时候,不管是一对多、一对一还是多对多,都只需要记住一点,在哪个实体类声明了外键,就由哪个类来维护关系,在保存数据时,总是先保存的是没有维护关联关系的那一方的数据,后保存维护了关联关系的那一方的数据