Hibernate關聯關系注解配置
什么是關聯關系?關聯關系有哪幾種?
關聯關系指實體之間的關系,也就是表與表之間的關系。一個關系用兩個屬性來描述,數量性和方向性。
從數量上來看,表與表之間主要有三種關系,一對一,一對多,多對多。
加上關系的方向,還有一個多對一。
hibernate中關聯關系的維護
在實際的業務開發中,對於兩個有關聯的數據庫實體,比如學生對教室,我們通常還需要在操作一方時,維護兩方彼此之間的關系。
關系的維護分為兩類:
1.級聯Cascade,在操作一方時,是否對另一方也執行同樣的操作。
2.外鍵的維護inverse,在操作一方時,是否自動維護外鍵關系。比如如果將 多方的對象添加給以一的一方,因為外鍵由多方維護,hibernate為了保證添加的這個多方對象的外鍵是正確的,會自動給這個多方的外鍵設置值(也就是一的一方的主鍵)
外鍵維護,在xml配置中使用inverse屬性,在注解中使用mappedBy注解來聲明。
cascade與inverse
1.cascade,指把對當前對象的操作 級聯到 關聯對象上。
一般在one to one ,one to many設置級聯。
配置了這個屬性后,當對當前對象執行如save等更新數據庫的操作時,當前實體所關聯的實體也會執行相應的操作。
2.inverse
默認值為true, 表示讓對方來維護關系。設為false,自己維護關系。
inverse主要有兩個作用:
1)維護外鍵
主控方保存時,是否自動update被控方的外鍵字段。外鍵字段指向的就是當前保存的實體。
2)維護級聯
決定當前設置的級聯是否有用,自己維護關系時,對方設置的級聯就不會生效,對方保存時不會讓本方也保存。而對方維護關系,則與此相反。
@mappedBy注解
1)mappedBy(name="對方標准代表當前實體的屬性“)
2)只存在於OneToOne,OneToMany,ManyToMany, 不能在ManyToOne中
3)與joincolumn或jointable互斥。因為joincolumn在擁有方聲明了被擁有方,而mappedby定義在被擁有方,指向擁有方。
4)一般擁有方為擁有外鍵的那一方,在一對多中是在多方。
有什么用:
讓擁有方來自動維護與當前實體的關系。與inverse對應。inverse=true
在注解中沒有設置mappedBy時,默認雙方都維護關系,就如inverse。
如何確定單向與雙向關聯
在實際開發中,是采用單向關聯還是雙向關聯,要看具體的業務需求,如果業務只需要在獲取一方的實體時獲取另一方的實體,而不是兩邊都能獲取,那就采用單向關聯。反之,如果需要在兩邊的實體中都能獲取到對方,就使用雙向關聯。
一對一
雙向關聯,每一方都能獲取到對方的實體
// CREATE TABLE `person` (
// `id` varchar(255) NOT NULL,
// `pname` varchar(255) DEFAULT NULL,
// `idcard` varchar(255),(外鍵)
// PRIMARY KEY (`id`)
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
// CREATE TABLE `idcard` (
// `id` varchar(255) NOT NULL,
// `cardnum` varchar(255) DEFAULT NULL,
// PRIMARY KEY (`id`)
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@Entity
@Table(name="person")
public class Person {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="pname")
private String pname;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="idcard")
private IdCard card;
}
@Entity
@Table(name="idcard")
public class IdCard {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="cardNum")
private String cardNum;
@OneToOne
@mappedBy(name="card")
private Person person;
}
單向關聯,一般讓外鍵所在的表作為主控方。
@Entity
@Table(name="person")
public class Person {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="pname")
private String pname;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="idcard")
private IdCard card;
}
@Entity
@Table(name="idcard")
public class IdCard {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="cardNum")
private String cardNum;
// 單向關聯,這邊不用保存對方的引用
}
一對多
// 表,多個student對應一個class
CREATE TABLE `student` (
`id` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`classId` varchar(255),(外鍵)
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `class` (
`id` varchar(255) NOT NULL,
`nane` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@Entity
@Table(name="person")
public class Person {
CREATE TABLE `teacher` (
`id` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `teacher_to_student` (
`id` varchar(255) NOT NULL,
`tid` varchar(255) NOT NULL,
`sid` varchar(255)NOT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
一對多,多對一雙向關聯,單向關聯只需要去掉一的那方對多方的引用。
@Entity
@Table(name="student")
public class Student {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="name")
private String name;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="classId")
private StudentClass class;
}
@Entity
@Table(name="class")
public class StudentClass {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="name")
private String name;
@OneToMany
//mappedBy和Joincolumn互斥
// mappedBy在一的一方
@mappedBy(name="classId")
private List<Student> students;
}
多對多關聯。分為兩種情況:
1.建立一個中間表,並為中間表建立持久化類。這樣就拆分成了兩個多對一關聯,配置如上。
2.不為中間表建立持久化類,而是交給hibernate去維護。
主控方:
@ManyToMany
@joinTable表示中間表
joinColumns 表示 當前實體在中間表的外鍵
inverseJoincolumns 關聯的另一方在中間表的外鍵
被控方:
ManyToMany(@MappedBy=主控方對象持有的被控方的屬性名)
@Entity
@Table(name="student")
public class Student {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="name")
private String name;
@ManyToOne(cascade=CascadeType.ALL)
@JoinTable(name = "teacher_to_student",
joinColumns = @JoinColumn(name = "sid"),
inverseJoinColumns = @JoinColumn(name = "tid"))
private Set<Teacher> teachers;
}
@Entity
@Table(name="teacher")
public class Teacher {
@Id
@GenericGenerator(name="uuidGenerator", strategy="uuid")
@GeneratedValue(generator="uuidGenerator")
private String id;
@Column(name="name")
private String name;
@ManyToMany(mappedBy="teachers",cascade=CascadeType.ALL)
private Set<Student> student;
}