最近在公司做一个小项目,框架的持久层我选用的是Hibernate annotation,用户和他收藏的网站的关系是多对多的关系,一个用户可以收藏多个他喜爱的网站;反过来,一个网站也可以被多个用户收藏。
因此在设计类的时候,我设计了一个Sysuser(用户)类和一个Website(网站)类。
其中@ManyToMany就不用说了,指明用户和网站之前是多对多的关系。这里需要说的是,在主控方的get那个set集合的方法上面需要再加上@JoinTable进行注解,其中name="user_web"就是指在数据库中体现多对多关系的中间表是user_web,指定之后在首次运行项目的时候会在数据库中自动生成这个中间表,而且这个中间表不需要写个类去对应,可以通过这两个有多对多关系的类去维护第三章表的数据。joinColumns=@JoinColumn(name="userid")这句话的意思是是定义中间表与Sysuser这个类外键关系,中间表是通过userid这一列产生外键关联的,而inverseJoinColumns是中间表参考另一张的表的主键生成的列。
其中的@ManyToMany也不用说了,指明网站与用户之间是多对多的关系。需要说明的是在被控方,需要加上mappedBy,例如这里的mappedBy="website"是产生关系的属性。
因此在设计类的时候,我设计了一个Sysuser(用户)类和一个Website(网站)类。
在配置注解的时候,由于在用户和网站之前,用户是主控方,网站是被控方。所以我在Sysuser类的getWebsite()方法上加了下面一段内容进行注解。
@ManyToMany(fetch=FetchType.EAGER,cascade={CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name="user_web",joinColumns=@JoinColumn(name="userid"),
inverseJoinColumns=@JoinColumn(name="webid"))
public Set<Website> getWebsite() {
return website;
}
public void setWebsite(Set<Website> website) {
this.website = website;
}
其中@ManyToMany就不用说了,指明用户和网站之前是多对多的关系。这里需要说的是,在主控方的get那个set集合的方法上面需要再加上@JoinTable进行注解,其中name="user_web"就是指在数据库中体现多对多关系的中间表是user_web,指定之后在首次运行项目的时候会在数据库中自动生成这个中间表,而且这个中间表不需要写个类去对应,可以通过这两个有多对多关系的类去维护第三章表的数据。joinColumns=@JoinColumn(name="userid")这句话的意思是是定义中间表与Sysuser这个类外键关系,中间表是通过userid这一列产生外键关联的,而inverseJoinColumns是中间表参考另一张的表的主键生成的列。
在Website类的getSysuser()方法上加了下面一段内容进行注解
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST},mappedBy="website")
public Set<Sysuser> getSysuser() {
return sysuser;
}
public void setSysuser(Set<Sysuser> sysuser) {
this.sysuser = sysuser;
}
其中的@ManyToMany也不用说了,指明网站与用户之间是多对多的关系。需要说明的是在被控方,需要加上mappedBy,例如这里的mappedBy="website"是产生关系的属性。
总结一下需要注意的几点:
1、只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
2、mappedBy标签一定是定义在the owned side(被控方,或者叫被拥有方),他指向the owning side(主控方,或者叫做拥有方);
3、mappedBy跟JoinColumn/JoinTable总是处于互斥的一方,可以理解为正是由于拥有方的关联被拥有方的字段存在,拥有方才拥有了被拥有方。mappedBy这方定义的JoinColumn/JoinTable总是失效的,不会建立对应的字段或者表。