標籤:效能 需要 join 類型 映射 count 簡單 onetomany 關係
在hibernate中,通常設定物件關係映射關係有兩種,一種是基於xml的方式,另一種是基於annotation的註解方式,熟話說,蘿蔔青菜,可有所愛,每個人都有自己喜歡的配置方式,我在試了這兩種方式以後,發現使用annotation的方式可以更簡介,所以這裡就簡單記錄下通過annotation來配置各種映射關係,在hibernate4以後已經將annotation的jar包整合進來了,如果使用hibernate3的版本就需要引入annotation的jar包。
一、單對象操作
@Entity ---> 如果我們當前這個bean要設定成實體物件,就需要加上Entity這個註解@Table(name="t_user") ----> 設定資料庫的表名public class User{ private int id; private String username; private String password; private Date born; private Date registerDate;
@Column(name="register_date") ---> Column中的name屬性對應了資料庫的該欄位名字,裡面還有其他屬性,例如length,nullable等等 public Date getRegisterDate() { return registerDate; } public void setRegisterDate(Date registerDate) { this.registerDate = registerDate; }
@Id ---> 定義為資料庫的主鍵ID (建議不要在屬性上引入註解,因為屬性是private的,如果引入註解會破壞其封裝特性,所以建議在getter方法上加入註解) @GeneratedValue ----> ID的建置原則為自動產生 public int getId() { return id; } public void setId(int id) { this.id = id; } ............}
最後只需要在hibernate.cfg.xml檔案裡面將該實體類加進去即可:
<!-- 基於annotation的配置 --> <mapping class="com.xiaoluo.bean.User"/><!-- 基於hbm.xml設定檔 --> <mapping resource="com/xiaoluo/bean/User.hbm.xml"/>
這樣我們就可以寫測試類別來進行我們的CRUD操作了。
二、一對多的映射(one-to-many)
這裡我們定義了兩個實體類,一個是ClassRoom,一個是Student,這兩者是一對多的關聯關係。
ClassRoom類:
@Entity@Table(name="t_classroom")public class ClassRoom{ private int id; private String className; private Set<Student> students; public ClassRoom() { students = new HashSet<Student>(); } public void addStudent(Student student) { students.add(student); } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } @OneToMany(mappedBy="room") ---> OneToMany指定了一對多的關係,mappedBy="room"指定了由多的那一方來維護關聯關係,mappedBy指的是多的一方對1的這一方的依賴的屬性,(注意:如果沒有指定由誰來維護關聯關係,則系統會給我們建立一張中間表) @LazyCollection(LazyCollectionOption.EXTRA) ---> LazyCollection屬性設定成EXTRA指定了當如果查詢資料的個數時候,只會發出一條 count(*)的語句,提高效能 public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } }
Student類:
@Entity@Table(name="t_student")public class Student{ private int id; private String name; private int age; private ClassRoom room; @ManyToOne(fetch=FetchType.LAZY) ---> ManyToOne指定了多對一的關係,fetch=FetchType.LAZY屬性工作表示在多的那一方通過消極式載入的方式載入對象(預設不是消極式載入) @JoinColumn(name="rid") ---> 通過 JoinColumn 的name屬性指定了外鍵的名稱 rid (注意:如果我們不通過JoinColum來指定外鍵的名稱,系統會給我們聲明一個名稱) public ClassRoom getRoom() { return room; } public void setRoom(ClassRoom room) { this.room = room; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
三、一對一映射(One-to-One)
一對一關聯性這裡定義了一個Person對象以及一個IDCard對象
Person類:
@Entity@Table(name="t_person")public class Person{ private int id; private String name; private IDCard card; @OneToOne(mappedBy="person") ---> 指定了OneToOne的關聯關係,mappedBy同樣指定由對方來進行維護關聯關係 public IDCard getCard() { return card; } public void setCard(IDCard card) { this.card = card; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
IDCard類:
@Entity@Table(name="t_id_card")public class IDCard{ private int id; private String no; private Person person; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } @OneToOne ---> OnetoOne指定了一對一的關聯關係,一對一中隨便指定一方來維護映射關係,這裡選擇IDCard來進行維護 @JoinColumn(name="pid") ---> 指定外鍵的名字 pid public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; }}
注意:在判斷到底是誰維護關聯關係時,可以通過查看外鍵,哪個實體類定義了外鍵,哪個類就負責維護關聯關係。
四、Many-to-Many映射(多對多映射關係)
多對多這裡通常有兩種處理方式,一種是通過建立一張中間表,然後由任一一個多的一方來維護關聯關係,另一種就是將多對多拆分成兩個一對多的關聯關係
1.通過中間表由任一一個多的一方來維護關聯關係
Teacher類:
@Entity@Table(name="t_teacher")public class Teacher{ private int id; private String name; private Set<Course> courses; public Teacher() { courses = new HashSet<Course>(); } public void addCourse(Course course) { courses.add(course); } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToMany(mappedBy="teachers") ---> 表示由Course那一方來進行維護 public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } }
Course類:
@Entity@Table(name="t_course")public class Course{ private int id; private String name; private Set<Teacher> teachers; public Course() { teachers = new HashSet<Teacher>(); } public void addTeacher(Teacher teacher) { teachers.add(teacher); } @ManyToMany ---> ManyToMany指定多對多的關聯關係 @JoinTable(name="t_teacher_course", joinColumns={ @JoinColumn(name="cid")}, inverseJoinColumns={ @JoinColumn(name = "tid") }) ---> 因為多對多之間會通過一張中間表來維護兩表直接的關係,所以通過 JoinTable 這個註解來聲明,name就是指定了中間表的名字,JoinColumns是一個 @JoinColumn類型的數組,表示的是我這方在對方中的外鍵名稱,我方是Course,所以在對方外鍵的名稱就是 rid,inverseJoinColumns也是一個 @JoinColumn類型的數組,表示的是對方在我這放中的外鍵名稱,對方是Teacher,所以在我方外鍵的名稱就是 tid public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
2.將Many-to-Many拆分成兩個One-to-Many的映射(Admin、Role、AdminRole)
Admin類:
@Entity@Table(name="t_admin")public class Admin{ private int id; private String name; private Set<AdminRole> ars; public Admin() { ars = new HashSet<AdminRole>(); } public void add(AdminRole ar) { ars.add(ar); } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(mappedBy="admin") ---> OneToMany關聯到了AdminRole這個類,由AdminRole這個類來維護多對一的關係,mappedBy="admin" @LazyCollection(LazyCollectionOption.EXTRA) public Set<AdminRole> getArs() { return ars; } public void setArs(Set<AdminRole> ars) { this.ars = ars; }}
Role類:
@Entity@Table(name="t_role")public class Role{ private int id; private String name; private Set<AdminRole> ars; public Role() { ars = new HashSet<AdminRole>(); } public void add(AdminRole ar) { ars.add(ar); } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(mappedBy="role") ---> OneToMany指定了由AdminRole這個類來維護多對一的關聯關係,mappedBy="role" @LazyCollection(LazyCollectionOption.EXTRA) public Set<AdminRole> getArs() { return ars; } public void setArs(Set<AdminRole> ars) { this.ars = ars; }}
AdminRole類:
@Entity@Table(name="t_admin_role")public class AdminRole{ private int id; private String name; private Admin admin; private Role role; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToOne ---> ManyToOne關聯到Admin @JoinColumn(name="aid") public Admin getAdmin() { return admin; } public void setAdmin(Admin admin) { this.admin = admin; } @ManyToOne ---> @JoinColumn(name="rid") public Role getRole() { return role; } public void setRole(Role role) { this.role = role; }}
小技巧:通過hibernate來進行插入操作的時候,不管是一對多、一對一還是多對多,都只需要記住一點,在哪個實體類聲明了外鍵,就由哪個類來維護關係,在儲存資料時,總是先儲存的是沒有維護關聯關係的那一方的資料,後儲存維護了關聯關係的那一方的資料,如:
Person p = new Person(); p.setName("xiaoluo"); session.save(p); IDCard card = new IDCard(); card.setNo("1111111111"); card.setPerson(p); session.save(card);
以上就是對hibernate annotation註解方式來配置映射關係的一些總結。
hibernate annotation註解方式來處理映射關係