版權聲明:本文為博主原創文章,如需轉載請標注轉載地址。
博客地址:http://www.cnblogs.com/caoyc/p/5598269.html
一、單向多對一和雙向多對一的區別
如果只需要從一方獲取另一方數據,就用單向多對一;如果需要從雙方都獲取對方數據,就用雙向多對一。
如果有兩個對象,一個為User對象,一個為Department對象,一個用戶只能屬於一個部門,而一個部門可以包含多個用戶。這樣就是多對一關系。如下圖
假設:我們需要通過用戶找到所對應的部門,不需要通過部門查詢該部門有哪些用戶,就采用單向多對一關系
如果:我們不僅需要通過用戶獲取所對應的部門,還需要通過部門對象獲取該部門下的用戶,那么就采用雙向多對一
二、單向多對一關系
Department.java
1 package com.proc.pojo; 2 3 import java.io.Serializable; 4 5 public class Department implements Serializable { 6 7 private Integer id; 8 private String deptname; 9 10 //提供構造方法 11 public Department() { 12 } 13 14 public Department(String deptname) { 15 this.deptname = deptname; 16 } 17 18 //getter和setter實現 19 public Integer getId() { 20 return id; 21 } 22 public void setId(Integer id) { 23 this.id = id; 24 } 25 public String getDeptname() { 26 return deptname; 27 } 28 public void setDeptname(String deptname) { 29 this.deptname = deptname; 30 } 31 }
User.java
1 package com.proc.pojo; 2 3 import java.io.Serializable; 4 5 public class User implements Serializable { 6 7 private Integer id; 8 private String name; 9 private Department dept; 10 11 //提供構造方法 12 public User() { 13 } 14 public User(String name) { 15 this.name = name; 16 } 17 //getter和setter實現 18 public Integer getId() { 19 return id; 20 } 21 22 public void setId(Integer id) { 23 this.id = id; 24 } 25 public String getName() { 26 return name; 27 } 28 public void setName(String name) { 29 this.name = name; 30 } 31 public Department getDept() { 32 return dept; 33 } 34 public void setDept(Department dept) { 35 this.dept = dept; 36 } 37 }
Department.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.proc.pojo"> <class name="Department" table="department"> <id name="id" type="int"> <generator class="native"></generator> </id> <property name="deptname" length="20" not-null="true"></property> </class> </hibernate-mapping>
User.hbm.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping package="com.proc.pojo"> 6 <class name="User"> 7 <id name="id" type="int"> 8 <generator class="native"></generator> 9 </id> 10 <property name="name" length="20" not-null="true"></property> 11 <many-to-one name="dept" column="deptid" class="Department" ></many-to-one> 12 </class> 13 </hibernate-mapping>
代碼講解:在配置User(多)->Department(一)時,采用外鍵映射,其中
name="dept":User對象dept屬性
class="Department":表示該dept屬性的類型是Department類型,因為User和Department在同一個包中,所以直接使用了類名稱
column="deptid":指定在用user表中,對應department表的中主鍵的列為deptid
這里並沒有指出user表中deptid對應的值department表中哪一列,默認為主鍵,這里也會自動給deptid列添加一個外鍵約束
foreign-key="none":不創建外鍵約束,如果將none改成其他的,即為指定外鍵名稱
測試代碼:
1 package com.proc.test; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.Transaction; 6 import org.hibernate.cfg.Configuration; 7 import org.junit.Test; 8 9 import com.proc.pojo.Department; 10 import com.proc.pojo.User; 11 12 public class TestOneToMany { 13 14 private static SessionFactory factory=new Configuration() 15 .configure() 16 .addClass(User.class) 17 .addClass(Department.class) 18 .buildSessionFactory(); 19 @Test 20 public void set(){ 21 22 Session session=factory.openSession(); 23 Transaction tran=session.beginTransaction(); 24 Department dept1=new Department("IT部"); 25 26 User user1=new User("caoyc"); 27 User user2=new User("zhh"); 28 29 user1.setDept(dept1); 30 user2.setDept(dept1); 31 32 session.save(dept1); 33 session.save(user1); 34 session.save(user2); 35 36 tran.commit(); 37 session.close(); 38 } 39 }
在控制台輸出SQL語句:
Hibernate: create table department (id integer not null auto_increment, deptname varchar(20) not null, primary key (id))
Hibernate: create table User (id integer not null auto_increment, name varchar(20) not null, deptid integer, primary key (id))
Hibernate: alter table User add constraint FK66lqw6kl2gcxhs44gamc91fbd foreign key (deptid) references department (id)
Hibernate: insert into department (deptname) values (?)
Hibernate: insert into User (name, deptid) values (?, ?)
Hibernate: insert into User (name, deptid) values (?, ?)
測試:如果將測試代碼中32-34行代碼改成
session.save(user1);
session.save(user2);
session.save(dept1);
在控制台輸出SQL語句:
Hibernate: create table department (id integer not null auto_increment, deptname varchar(20) not null, primary key (id))
Hibernate: create table User (id integer not null auto_increment, name varchar(20) not null, deptid integer, primary key (id))
Hibernate: alter table User add constraint FK66lqw6kl2gcxhs44gamc91fbd foreign key (deptid) references department (id)
Hibernate: insert into User (name, deptid) values (?, ?)
Hibernate: insert into User (name, deptid) values (?, ?)
Hibernate: insert into department (deptname) values (?)
Hibernate: update User set name=?, deptid=? where id=?
Hibernate: update User set name=?, deptid=? where id=?
這里多出了兩行update User代碼,也就是在我們先添加向user表中插入數據時,而還在department總還沒有數據,當插入department數據后,在通過update的方式來修改user表
總結:在我們插入多對一關系時,需要先保存(一)的一方,然后在保存(多)的一方,這樣可以減少SQL執行語句,如果是單向多對一關系,在添加多對一關系,只需要在(多)的一方的映射文件(.hbm.xml)中添加many-to-one就可以了
單向多對一刪除操作:
a、刪除(多)的一方(User),刪除成功
b、刪除(一)的一方(Department),如果user表中沒有該部門的用戶,則刪除成功
c、刪除(一)的一方(Department),如果user表中還有改部門的用戶,則刪除失敗,因為有外鍵約束
三、雙向多對一操作
第一步:在Department.java中添加一個users屬性,並提供get和set方法
1 private Set<User> users; 2 public Set<User> getUsers() { 3 return users; 4 } 5 public void setUsers(Set<User> users) { 6 this.users = users; 7 }
第二步:在Department.hbm.xml中添加關聯映射
既可以通過User的到Department,也可以通過Department得到Set<User>
雙向多對一刪除:
a、刪除(多)的一方,總是成功
b、刪除(少)的一方,如果inverse=“false”,成功
c、刪除(少)的一方,如果inverse=“true”,失敗