• 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”,失败

  • 相关阅读:
    Aop 打印参数日志时,出现参数序列化异常。It is illegal to call this method if the current request is not in asynchron
    Nginx 配置反向代理ip
    springboot 的启动流程
    sqlserver 查看表死锁
    idea 中 下载源码:Sources not download for:
    sqlserver exists 与 in 的区别
    sqlserver case when 的使用方法
    Java项目启动时执行指定方法的几种方式
    使用多线程并获取执行结果
    nodejs实现一个文件存储服务
  • 原文地址:https://www.cnblogs.com/caoyc/p/5598269.html
Copyright © 2020-2023  润新知