写在前面
这里的关系是指:对象之间的关系,并不是数据库的关系
如:关系有单向和双向之分,但是在数据库中,单向关系和双向关系其实并没有什么区别,
这里的单双向指的是对象之间是否能够相互访问
铁律: 1、凡是双向关联,必设mappedBy
因为根本都没必要在2个表中都存在一个外键关联,在数据库中只要定义一遍就可以了
mappedBy的意思就是“被映射”,即mappedBy这方不用管关联关系(即不生成外键字段),关联关系交给另一方处理
2、双向关系在程序中要设定双向关联
存在以下关联关系
1.一对一
有两种策略可以实现一对一的关联映射:
1.主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系;
数据库表不会有额外的字段来维护它们之间的关系,仅通过表的主键来关联
2.唯一外键关联:外键关联,本来是用于多对一的配置,
但是如果加上唯一的限制之后,也可以用来表示一对一关联关系
唯一外键关联(单向)
@OneToOne 写在被引用对象的实体类中
@JoinColum 为数据库表中这个外键指定个字段名称
1 @Entity 2 public class Husband { 3 private int id; 4 private String name; 5 private Wife wife; 6 7 @OneToOne 8 @JoinColumn(name="wifeID") 9 public Wife getWife() { 10 return wife; 11 } 12 public void setWife(Wife wife) { 13 this.wife = wife; 14 } 15 @Id 16 @GeneratedValue(strategy=GenerationType.AUTO) 17 public int getId() { 18 return id; 19 } 20 public void setId(int id) { 21 this.id = id; 22 } 23 public String getName() { 24 return name; 25 } 26 public void setName(String name) { 27 this.name = name; 28 } 29 }
唯一外键关联(双向)
mappedBy作用
是指定这个一对一关联是被Husband类的 wife属性(准确说是getWife方法)做的映射
Wife这边不生成外键字段,而是交给 Husband去生成外键字段
1 @Entity 2 public class Wife { 3 private int id; 4 private String name; 5 private Husband husband; 6 @OneToOne(mappedBy="wife") 7 public Husband getHusband() { 8 return husband; 9 } 10 public void setHusband(Husband husband) { 11 this.husband = husband; 12 }
主键关联(单向)
@PrimaryKeyJoinColumn
主键关联(双向)
mappedBy
联合主键关联(参考的那张表的主键不唯一时 会使用到)
@JoinColumns
注解联合主键一对一联系,然后再使用@JoinColumn 来注解当前表中的外键字段名,
并指定关联哪个字段,使用referencedColumnName指定哪个字段的名称
1 @OneToOne 2 @JoinColumns( 3 { 4 @JoinColumn(name="wifeId", referencedColumnName="id"), 5 @JoinColumn(name="wifeName", referencedColumnName="name") 6 } 7 ) 8 public Wife getWife() { 9 return wife; 10 }
2.多对一
@ManyToOne
3.一对多
@OneToMany
4.多对多
@ManyToMany
1 @ManyToMany 2 @JoinTable(name="t_s", 3 joinColumns={@JoinColumn(name="teacher_id")}, //会自动参考teahcer的 ID 4 inverseJoinColumns={@JoinColumn(name="student_id")} //会自动参考student的 ID 5 ) 6 public Set<Student> getStudents() { 7 return students; 8 } 9 public void setStudents(Set<Student> students) { 10 this.students = students; 11 }
注:关联关系中的CRUD_Cascade_Fetch
@OneToMany
(mappedBy="group",
cascade={CascadeType.ALL},fetch=FetchType.EAGER
)
1.设定cascade 可以设定在持久化时对于关联关系对象的操作(级联更新)(CUD ,R归Fetch管)
2.cascade仅仅是帮助我们省了编程的麻烦而已,不要把它的作用看的太大
3.fetch(FetchType.EAGER,(会被关联自动查询出来)FetchType.Lazy(不会自动关联查询出来,用到的时候才会去查询))
如老师里面有 学生集合,当老师被查询时,这个老师的学生集合被直接加载出来,不管是否学生有没有用到 EAGER
学生集合不会被直接加载,而是等到需要用到学生的时候,才会去加载学生集合 Lazy
a) 铁律:双向不要两边设置Eager (会有多余的查询语句发出)
b) 对多方设置fetch的时候要谨慎,结合具体应用,一般用Lazy 不用 eager,
特殊情况(多方数量不多的可以考虑,提高效率时可以考虑)
4.如果想消除关联关系,先设定关系为null,再删除对应记录(如果不设定为null,就会级联删除),
如果不删除记录,该记录就变成垃圾数据
5.集合映射
1.Set
2.List
a) @OrderBy("name ASC")
//使用 @OrderBy注解List中使用哪个字段进行排序,可以组合排序,中间使用逗号分开
3.Map
a) @MapKey(name="id") //注解使用哪个字段为key
6.继承关系(不重要)
使用@Inheritance 注解为继承映射,再使用strategy属性来指定继承映射的方式
strategy有三个值:InheritanceType.SINGLE_TABLE 单表继承
InheritanceType.TABLE_PER_CLASS 类表继承
InheritanceType.JOINED 具体表继承
a)单表继承 SINGLE_TABLE 把所有的属性都存储到一个表中,另外需要加入一个标识字段(表示哪个具体的子类) 使用@DiscriminatorColumn 标识字段的字段名,及字段类型 使用@DiscriminatorValue 来注解标识字段的值 b)类表继承 TABLE_PER_CLASS 每个具体类 映射成一个表 ,子类之间的ID不能重复 @TableGenerator来申明一个表主键生成策略 @GeneratedValue(generator="t_gen", strategy=GenerationType.TABLE)来注解生成策略为表生成策略,并且指定表生成策略的名称 c)具体表继承 JOINED 每个类 映射成一个表 父类中包含了子类公共的一些字段,父类中一个ID对应一个子类 只需要设置@Inheritance(strategy=InheritanceType.JOINED)
7.组件映射(值对象 和 实体对象)
@Embeddable
@Embedded //用于注解组件映射,表示嵌入对象的映射
1 @Embedded 2 public Wife getWife() { 3 return wife; 4 } 5 public void setWife(Wife wife) { 6 this.wife = wife; 7 }
/*Wife成了Husband的一部分,Wife中的这些字段,也会放到Husband中,Wife在这里只是一个对象,不需要任何注解*/