Hibernate 多对多 一对多 多对一 配置解析案例


  - 多对多
  - 一对多
  - 多对一
  - many-to-many
  - many-to-one
  - one-to-many
  - 关系映射
  - Hibernate
  - 关系映射
---

# 此案例用于理解脏检查,以及Hibernate关系映射的配置

 pom.xml```XML

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>HibernateCase</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.12.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.hynnet/oracle-driver-ojdbc -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>12.1.0.2</version>
        </dependency>
    </dependencies>

</project>


## 数据库的关系

```SQL
--部门
CREATE TABLE depa(
    ID NUMBER NOT NULL,
    NAME NVARCHAR2 (50) NOT NULL
);

--职员
CREATE TABLE emp(
    ID NUMBER NOT NULL,
    NAME NVARCHAR2 (50) NOT NULL,
    depa_id NUMBER NOT NULL
);

--职位
CREATE TABLE post(
    ID NUMBER NOT NULL,
    NAME NVARCHAR2 (50) NOT NULL
);

--职员职位
CREATE TABLE emp_post(
    emp_id NUMBER NOT NULL,
    post_id NUMBER NOT NULL
);
```

`emp_post` 职员职位表为中间表,实体类可以不存在

## 实体类

### Depa

```java
package com.entity;

import java.util.HashSet;
import java.util.Set;

public class Depa {
    private Integer id;
    private String name;
    private Set<Emp> emps = new HashSet<Emp>();

    @Override
    public String toString() {
        return "Depa{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public Set<Emp> getEmps() {
        return emps;
    }

    public void setEmps(Set<Emp> emps) {
        this.emps = emps;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
```

### Emp

```java
package com.entity;

import java.util.HashSet;
import java.util.Set;

public class Emp {
    private Integer id;
    private String name;
    private Depa depaid;
    private Set<Post> posts = new HashSet<Post>();

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public Set<Post> getPosts() {
        return posts;
    }

    public void setPosts(Set<Post> posts) {
        this.posts = posts;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Depa getDepaid() {
        return depaid;
    }

    public void setDepaid(Depa depaid) {
        this.depaid = depaid;
    }
}
```

### Post

```java
package com.entity;

import java.util.HashSet;
import java.util.Set;

public class Post {
    private Integer id;
    private String name;
    private Set<Emp> emps = new HashSet<Emp>();

    @Override
    public String toString() {
        return "Post{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public Set<Emp> getEmps() {
        return emps;
    }

    public void setEmps(Set<Emp> emps) {
        this.emps = emps;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
```

 

`Emp` 实体类 和 `Post` 实体类 都有对方的 `Set<?>` 集合,这也是操作中间表 `emp_post` 的关键属性

## 对实体类关系映射配置

 depa.hbm.xml

<?xml version="1.0"?>
<!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.entity">
    <class name="Depa" table="depa">
        <id name="id">
            <generator class="increment"/>
        </id>
        <property name="name"/>


        <!--一对多 name为实体类属性名 class为对应外键对应实体类-->
        <!--table 实体类对象数据来源数据库表名 cascade维护方式-->
        <!--inverse 指定由哪一方来维护之间的关联关系 当一方中指定了"inverse=false"(默认),那么那一方就有责任负责之间的关联关系-->
   

     <set name="emps" table="emp" cascade="all" inverse="true">
            <!--column 为emp数据库关联depa的外键名-->
            <key column="depa_id"></key>
            <!--class emps的单个实体数据为哪个实体类-->
            <one-to-many class="Emp"/>
        </set>
    </class>


 

 emp.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--package为命名空间 子节点有多个类的全在com.entity包里-->
<!--(如果不写,下面 <class name="Emp" name值"Emp"需要改成"com.entity.Emp")-->
<hibernate-mapping package="com.entity">
    <class name="Emp" table="emp">
        <!--主键-->
        <id name="id">
            <!--自增方式-->
            <generator class="increment"/>
        </id>
        <!--普通数据列-->
        <property name="name"/>
        <!--多对一 name为实体类属性名 class为对应外键对应实体类 column为数据库外键名(如果与name值一样可以忽略)-->
        <many-to-one name="depaid" class="Depa" column="depa_id"/>
        <!--多对多 name为实体类属性名 table 关联的中间表 cascade 维护方式 save-update 为维护方式是新增或修改-->
        <set name="posts" table="emp_post" cascade="save-update">
            <!--中间表emp_post 对应emp的外键-->
            <key column="emp_id"></key>
            <!--class 多对多的实体类 column 中间表emp_post 对应Post的外键-->
            <many-to-many class="Post" column="post_id"/>
        </set>
    </class>
</hibernate-mapping>


 

 post.hbm.xml

<?xml version="1.0"?>
<!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.entity">
    <class name="Post" table="post">
        <id name="id">
            <generator class="increment"/>
        </id>
        <property name="name"/>


        <!--多对多 name为实体类属性名 table 关联的中间表 cascade 维护方式 save-update 为维护方式是新增或修改-->
     

   <set name="emps" table="emp_post" cascade="save-update">
            <!--中间表emp_post 对应post的外键-->
            <key column="post_id"></key>
            <!--class 多对多的实体类 column 中间表emp_post 对应Emp的外键-->
            <many-to-many class="Emp" column="emp_id"/>
        </set>
    </class>

将实体类的 `XML` 映射到 hibernate.cfg.xml 配置

### hibernate.cfg.xml```XML

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
        <property name="connection.username">system</property>
        <property name="connection.password">simon</property>
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="current_session_context_class">thread</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <mapping resource="com/entity/depa.hbm.xml"/>
        <mapping resource="com/entity/emp.hbm.xml"/>
        <mapping resource="com/entity/post.hbm.xml"/>
    </session-factory>
</hibernate-configuration>


```

 Hibernate工具类 HibernateUtil

```java
package com.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static Configuration configuration;
    private static final SessionFactory factory;

    static {
        configuration = new Configuration().configure("hibernate.cfg.xml");
        factory = configuration.buildSessionFactory();
    }

    public static Session getSession() {
        return factory.getCurrentSession();
    }
}
```

## 测试类 Test

package com.test;

import com.entity.Depa;
import com.entity.Emp;
import com.entity.Post;
import com.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class Test {
    public static void main(String[] args) {
        Session session = HibernateUtil.getSession();
        Transaction transaction = session.beginTransaction();

        System.out.println("查询ID为1的职员数据");
        Emp emp = session.get(Emp.class, 1);
        System.out.println(emp);

        System.out.println("通过职员得到中间表emp_post数据");
        for (Post post : emp.getPosts()) {
            System.out.println(post);
        }

        System.out.println("清除职员中间表emp_post的数据");
        emp.getPosts().clear();

        System.out.println("查询ID为2的职位数据");
        Post post = session.get(Post.class, 2);
        System.out.println(post);

        System.out.println("将查到的职位给职员新增中间表emp_post数据");
        emp.getPosts().add(post);

        System.out.println("查询ID为1的职员数据");
        emp = session.get(Emp.class, 1);
        System.out.println(emp);

        System.out.println("通过职员得到中间表emp_post数据");
        for (Post temp : emp.getPosts()) {
            System.out.println(temp);
        }

        System.out.println("通过职员得到部门表depa数据");
        System.out.println(emp.getDepaid());

        System.out.println("查询ID为1的部门数据");
        Depa depa = session.get(Depa.class, 1);
        System.out.println(depa);

        System.out.println("将查到的部门depa给职员emp利用脏检查修改");
        emp.setDepaid(depa);

        System.out.println("查询ID为1的职员数据");
        emp = session.get(Emp.class, 1);
        System.out.println(emp);

        System.out.println("通过职员得到部门表depa数据");
        System.out.println(emp.getDepaid());

        System.out.println("查询ID为2的部门数据");
        depa = session.get(Depa.class, 2);
        System.out.println(depa);

        System.out.println("得到部门对象所属职员");
        for (Emp e : depa.getEmps()) {
            System.out.println(e);
        }

        System.out.println("利用脏检查删除部门对象所属的ID为1的职员");
        depa.getEmps().remove(emp);

        System.out.println("查询ID为2的部门数据");
        depa = session.get(Depa.class, 2);
        System.out.println(depa);

        System.out.println("得到部门对象所属职员");
        for (Emp e : depa.getEmps()) {
            System.out.println(e);
        }

        //不提交,则上面的结果不会对数据库执行操作
//        transaction.commit();
    }
}
```

 控制台输出

看看测试类代码对数据库的数据进行了哪些操作

```
查询ID为1的职员数据

Hibernate:
    select
        emp0_.id as id1_1_0_,
        emp0_.name as name2_1_0_,
        emp0_.depa_id as depa_id3_1_0_
    from
        emp emp0_
    where
        emp0_.id=?
Emp{id=1, name='张三'}


通过职员得到中间表emp_post数据

Hibernate:
    select
        posts0_.emp_id as emp_id1_2_0_,
        posts0_.post_id as post_id2_2_0_,
        post1_.id as id1_3_1_,
        post1_.name as name2_3_1_
    from
        emp_post posts0_
    inner join
        post post1_
            on posts0_.post_id=post1_.id
    where
        posts0_.emp_id=?
Post{id=1, name='职员'}


清除职员中间表emp_post的数据
查询ID为2的职位数据

Hibernate:
    select
        post0_.id as id1_3_0_,
        post0_.name as name2_3_0_
    from
        post post0_
    where
        post0_.id=?
Post{id=2, name='主管'}


将查到的职位给职员新增中间表emp_post数据
查询ID为1的职员数据
Emp{id=1, name='张三'}
通过职员得到中间表emp_post数据
Post{id=2, name='主管'}
通过职员得到部门表depa数据

Hibernate:
    select
        depa0_.id as id1_0_0_,
        depa0_.name as name2_0_0_
    from
        depa depa0_
    where
        depa0_.id=?
Depa{id=2, name='美工部'}


查询ID为1的部门数据

Hibernate:
    select
        depa0_.id as id1_0_0_,
        depa0_.name as name2_0_0_
    from
        depa depa0_
    where
        depa0_.id=?
Depa{id=1, name='销售部'}


将查到的部门depa给职员emp利用脏检查修改
查询ID为1的职员数据
Emp{id=1, name='张三'}
通过职员得到部门表depa数据
Depa{id=1, name='销售部'}
查询ID为2的部门数据
Depa{id=2, name='美工部'}
得到部门对象所属职员

Hibernate:
    select
        emps0_.depa_id as depa_id3_1_0_,
        emps0_.id as id1_1_0_,
        emps0_.id as id1_1_1_,
        emps0_.name as name2_1_1_,
        emps0_.depa_id as depa_id3_1_1_
    from
        emp emps0_
    where
        emps0_.depa_id=?
Emp{id=1, name='张三'}


利用脏检查删除部门对象所属的ID为1的职员
查询ID为2的部门数据
Depa{id=2, name='美工部'}
得到部门对象所属职员
```

[点击下载案例] [1]

 https://gitee.com/admin-simon/HibernateCase/repository/archive/master.zip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值