hibernate 註解方式講解映射關系
註解方式講解映射關系
1 One-To-One Unidirectional with Foreign Key
單向關聯外鍵方式。
1.1 關系如下
學生和地址關系的例子。一個學生住在一個地址上。一個地址只能由一個學生占用。
1.2 Address代碼:
package com.daodaofun.domain; import javax.persistence.*; @Entity @Table(name="STUDENT") public class Student { @Id @GeneratedValue @Column(name="STUDENT_ID") private Long id; @Column(name = "FIRST_NAME") private String firstName; @Column(name = "LAST_NAME") private String lastName; @OneToOne @JoinColumn(name = "ADDRESS_ID") private Address address; public Student() { } public Long getId() {return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; }public void setLastName(String lastName) { this.lastName = lastName; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
這樣可以不用寫hbm.xml,還是挺方便的。此時註意在Student一端配置了JoinColumn,也就是關聯的列,那麽就會在Student表當中添加home_address_id這一列,作為外鍵。
外鍵名稱如果需要指定可以使用@Foreignkey,遺憾的是這個版本已經是過時了,JPA的註解沒有過時,但是無法加在這個屬性之上,所以要麽使用過時的註解,要麽你忍受,或者你自行建表。
2 One-To-One Bidirectianal
所謂的雙向配置也差不了多少,就是在另外一端一樣加上引用即可,即在Address這一段一樣持有Student。並且加上如下註解即可:
@OneToOne
private Student student;
但是這樣有個問題,會導致雙外鍵,這個明顯屬於冗余,這個時候我們需要指明誰來主導,外鍵由誰來建設的問題,所以我們需要額外設置一下如下:
@OneToOne(mappedBy = "address")
private Student student;
這樣就比較合理了。
3 Many-To-One Bidirectional
多對一雙向
我們以學生與大學的關系為例,一所大學可以有很多學生。
關系圖如下:
3.1 University代碼:
-··在一的一方配置OneToMany,同樣的由於我們會將外鍵設置在多的一方,所以要將這個建設權交給對方,所以要加上mappedBy。
package com.daodaofun.domain; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name="UNIVERSITY") public class University { @Id @GeneratedValue @Column(name="UNIVERSITY_ID") private Long id; @Column(name="NAME") private String name; @Column(name="COUNTRY") private String country; @OneToMany(mappedBy = "university",cascade = CascadeType.ALL) private List<Student> students; public University() { } public University(String name, String country) { this.name = name; this.country = country; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } }
3.2 Student代碼:
package com.daodaofun.domain; import javax.persistence.*; @Entity @Table(name="STUDENT") public class Student { @Id @GeneratedValue @Column(name="STUDENT_ID") private Long id; @Column(name = "FIRST_NAME") private String firstName; @Column(name = "LAST_NAME") private String lastName; @ManyToOne(optional = false) @JoinColumn(name = "UNIVERSITY_ID") private University university; public Student() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public University getUniversity() { return university; } public void setUniversity(University university) { this.university = university; } }
在多的一方,同樣的指明建設外鍵是什麽列加上JoinColumn,此外這裏有一個optional=false,這個是什麽含義呢?
(Optional) Whether the association is optional. If set
to false then a non-null relationship must always exist.
關聯關系是否可選,如果設置為了false,那麽就必須為非空關系。
4 Many-To-Many Bidirectional
雙向多對多
在多對多關聯中,使用了一個額外的表(稱為聯接表),其主鍵是兩個關聯表的主鍵的組合。換句話說,聯接表和關聯表之間存在外鍵關聯表。
討論一個學生和學科關系的例子。一名學生可以註冊多個科目。一個科目可以有多個學生註冊。
關系圖如下:
向這種多多關系其實都是通過一張中間表來體現的。
4.1 Student代碼:
package com.daodaofun.domain; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity @Table(name="STUDENT") public class Student { @Id @GeneratedValue @Column(name="STUDENT_ID") private Long id; @Column(name = "FIRST_NAME") private String firstName; @Column(name = "LAST_NAME") private String lastName; @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "STUDENT_SUBJECT",joinColumns = {@JoinColumn(name = "STUDENT_ID")}, inverseJoinColumns = {@JoinColumn(name = "SUBJECT_ID")}) private List<Subject> subjects = new ArrayList<>(); public Student() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public List<Subject> getSubjects() { return subjects; } public void setSubjects(List<Subject> subjects) { this.subjects = subjects; } }
4.2 subject代碼:
package com.daodaofun.domain; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity @Table(name = "SUBJECT") public class Subject { @Id @GeneratedValue @Column(name = "SUBJECT_ID") private Long id; @Column(name = "name") private String name; @ManyToMany(mappedBy = "subjects") private List<Student> students = new ArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } }
這裏可以指定任意一方來負責設置表的生成方式,此處是由subjects來設置,需要註意的是
@JoinTable(name = "STUDENT_SUBJECT",joinColumns = {@JoinColumn(name = "STUDENT_ID")},
inverseJoinColumns = {@JoinColumn(name = "SUBJECT_ID")})通過name指定了中間表名稱,然後指明需要生成的列,兩列就是student表和subject表各自的主鍵。
以上幾種是比較實用的映射關系方式,hibernate可以配置映射的方式特別多,上面幾種差不多夠用了。
hibernate 註解方式講解映射關系