基于注解的关联关系Hibernate(2)——详解+源码

来源:互联网 发布:ajaxupload.js cdn 编辑:程序博客网 时间:2024/05/21 17:49

Hibernate关系映射注解配置

首先针对不同的关系映射类型给出主要的注解再进行代码解释:

  • 一对一单向关联外键

主控类要持有被控类的对象,并且主控类中要有@OneToOne注解,@OneToOne注解包含必填cascade属性,表示级联操作.

在哪个model(实体)中应用cascade属性就表示该表的操作会级联另一个表.

@JoinColumn注解用来指明外键.
name属性(必选):指定外键名.指定的外键名必须是与(关联表)另一类的主键一致
unique属性(可选):表示外键的值是否唯一,一对一关联中外键的值是唯一的.一对多关联、多对多关联,外键的值则不唯一.
一对一单表关联的时候保存对象方式,保存的时候先保存被控方,然后再保存主控方,
例子:
主控类

public class Students {//主控类,持有被控类的对象    private IdCard card;//持有被控类的对象    private int sid;    private String gender;    private Date birthday;    public Students(){      }    public Students(IdCard card,String gender,Date birthday){         this.card = card;         this.gender = gender;         this.birthday = birthday;    }    @OneToOne(cascade=CascadeType.ALL)//级联关系,全级联    @JoinColumn(name="pid",unique=true)    //@JoinColum设置了外键的名称为pid(数据库字段名),    //如果不设置,则默认为另一类的属性名+ _id,外键名与另一类的主键一致    public IdCard getCard() {        return card;    }    public void setCard(IdCard card) {        this.card = card;    }    @Id    @GeneratedValue//自动增长    public int getSid() {        return sid;    }    ......部分代码略

被控类:

public class IdCard {//被控类    @Id    @GeneratedValue(generator="pid")//指定生成器    @GenericGenerator(name = "pid", strategy = "assigned")//手工赋值    @Column(length=18)//字段长度    private String pid;//身份证号    private String sname;//学生姓名    public IdCard(){    }......部分代码略
  • 一对一外键关联映射(双向)

主控表Student和单向中的一样,在被控表IdCard中同样得使用@OneToOne并且要带上mappedBy属性。如果不加则会生成一个新外键student_id(默认关联表主键+_id)

mappedby=”idcard”需要指向与他关联对象的一个属性

mappedBy属性,是用来指明从表(被控方)被谁关联(抛出控制权).不需使用@JoinColumn注解.如果不使用mappedBy属性,并且使用@JoinColumn注解指定另一方的主键,则在保存数据时就会发生错误,类似死锁问题.因为双方都是一方.使@JoinColumn都会在自己表建立外键.
例子:

public class IdCard {//被控类    @Id    @GeneratedValue(generator="pid")//指定生成器    @GenericGenerator(name = "pid", strategy = "assigned")//手工赋值    @Column(length=18)//字段长度    private String pid;//身份证号    private String sname;//学生姓名    @OneToOne(mappedBy="idcard")//是主控方的外键的属性值     //mappedby="idcard"需要指向与他关联对象的一个属性 Student表中的 private IdCard idcard    private Students stu;    public IdCard(){    }    ......部分代码略

注意双向关联中,双方类中都存在另一方类类型的属性

public class Students {//主控类,持有被控类的对象    private IdCard idcard;//另一方类类型的属性......}public class IdCard {//被控类    ......    @OneToOne(mappedBy="idcard")    private Students stu;//另一方类类型的属性    ......}
  • 多对一关联映射
    在多的一端配置:@ManyToOne、@JoinColumn.
    @ManyToOne注解中cascade:指定级联关(CascadeType.ALL).
    fetch:指定抓取策略(FetchType.EAGER).

@JoinColumn注解中name属性:指明作为外键的列名

默认情况下,关联的实体的主键一般是用来做外键的,但如果此时不想主键作为外键.则需要设置referencedColumnName属性.
referencedColumnName属性:指定外键表与参照表的哪个属性进行关联(指定参照表字段的列名).

public class Students {//多方......@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.EAGER)//抓取策略    @JoinColumn(name="cid",referencedColumnName="cname")//指定外键基于ClassRoom    public ClassRoom getClassRoom() {        return classRoom;    }    ......public class ClassRoom {    @Id    private String cid;    private String cname;

这里写图片描述

  • 一对多关联映射(单向)
    无论使用一对多还是多对一,外键字段都得是存在多方的表当中.在一方引入多方的集合并在其上使用

@OneToMany(cascade{CascadeType.ALL},fetch=FetchType.LAZY)
@JoinColumn(name=”cid”);指定外键名字:在多的一端加上外键cid,来维护他们之间的关系
使用多对一时,多方的抓取策略fetch一般设置为EAGER、一方设置为LAZY.
当使用单向的一对多关联时,要先保存多方的数据再保存一方的数据.
例子:

public class ClassRoom {    private String cid;    private String cname;    @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY)    @JoinColumn(name="cid")    private Set<Students>  stus;//一方持有多方的集合......
  • 一对多(多对一)关联映射(双向)

有两种实现方式
一种没有用mappedBy

多方:持有一方的引用
@ManyToOne(cascade{CascadeType.ALL},fetch=FetchType.EAGER)
@JoinColumn(name=”cid”)
一方:持有多方的集合
@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
@JoinColumn(name=”cid”)
一对多双边时,@JoinColumn 的name属性要一致
结果是:
这里写图片描述
使用了mappedBy:
一端:
@OneToMany(mappedBy=”classRoom”)
@JoinColumn(name=”cid”)
/**
- 一对多双向,在一的一端中设置mappedBy
- 说明多的一端为主导
*/
多端:
@ManyToOne

  • 多对多关联映射(单向)
  • -
public class Students{.......@ManyToMany@JoinTable(            name = "teachers_students",            joinColumns = {@JoinColumn(name = "sid")},//指定当前对象的外键            inverseJoinColumns = {@JoinColumn(name = "tid")}//    )......}

其中一个多方持有另一个多方的集合对象.
多对多关系中,必须存在一个中间表来表示两者的关系
@JoinTable注解用来标识中间表.
joinColumns属性用来标识中间表字段的名称.
inverseJoinColumns属性用来标识关联的表位于中间表字段的名称.

  • 多对多关联映射(双向)
    多对多这里通常有两种处理方式,一种是通过建立一张中间表,然后由任一一个多的一方来维护关联关系,另一种就是将多对多拆分成两个一对多的关联关系

Students类保持不变,在关联的类ClassRoom中加入
@ManyToMany(mappedBy=”teachers”)

简单的理解:双向关联的注解配置就是在单向注解配置的基础上,在关联表的类中加上mappedBy属性,来指明本类把关系的维护交给对方的属性来维护。

注意要素:

  1. 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;且一对一时,mappedBy应该设置为另一方的主键属性名,多对多时,mappedBy应该设置为另一方的Set类型的属性名.
  2. mappedBy标签一定是定义在the owned side(被拥有方的),他指向the owning side(拥有方)。关系的拥有方负责关系的维护,在拥有方建立外键,拥有方需有@JoinColumn。
  3. mappedBy跟JoinColumn/JoinTable总是处于互斥的一方
  4. 通过hibernate来进行插入操作的时候,不管是一对多、一对一还是多对多,都只要记住一点,在哪个实体类声明了外键@JoinColumn,就由哪个类来维护关系。在保存数据时,总是先保存的是没有维护关联关系的那一方的数据,后保存维护了关联关系的那一方的数据,

对比源码的下载

原创粉丝点击