版权声明:本文为博主原创文章,如需转载请标注转载地址。
博客地址: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”,失败