Hibernate 多对一关联查询

Posted JustDo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate 多对一关联查询相关的知识,希望对你有一定的参考价值。

 版权声明:本文为博主原创文章,如需转载请标注转载地址

 博客地址: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”,失败

以上是关于Hibernate 多对一关联查询的主要内容,如果未能解决你的问题,请参考以下文章

hibernate多对一关联映射两种形式的理解

第六章 Hibernate关联映射

Hibernate-03 关联映射

Hibernate框架单向多对一关联映射关系

Hibernate中一对多和多对一关系

hibernate多对多查询