Hibernate一对多级联操作

时间:2021-04-11 20:58:16

以客户和联系人为例:客户是一,联系人是多
表的关系:将一方的主键在多方中设置为外键

第一步 创建两个实体类,客户和联系人,并在两个实体类之中互相表示关系

Customer实体类(一方)

package entity;

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

public class Customer {

    private Integer cid;
    private String custName;
    /* * 一个客户有多个联系人 * hibernate要求使用set集合在一方中表示多方 */
    private Set<LinkMan> linkMans = new HashSet<LinkMan>();
    public Set<LinkMan> getLinkMans() {
        return linkMans;
    }
    public void setLinkMans(Set<LinkMan> linkMans) {
        this.linkMans = linkMans;
    }

    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
    public String getCustName() {
        return custName;
    }
    public void setCustName(String custName) {
        this.custName = custName;
    }

}

LinkMan实体类(多方)

package entity;

public class LinkMan {

    private Integer lid;
    private String lkmName;
    /* * 一个联系人只属于一个客户 */
    private Customer customer;
    public Integer getLid() {
        return lid;
    }
    public void setLid(Integer lid) {
        this.lid = lid;
    }
    public String getLkmName() {
        return lkmName;
    }
    public void setLkmName(String lkmName) {
        this.lkmName = lkmName;
    }
}

第二步 配置每个实体类的映射关系,包括实体类与数据库中表的映射,以及一对多关系的配置

Customer.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>
    <!-- Class映射到表 -->
    <class name="entity.Customer" table="t_customer">
        <!-- 主键映射(重要) -->
        <id name="cid" column="cid">
            <!-- Native设置id为自增长 -->
            <generator class="native"></generator>
        </id>
        <!-- 普通属性映射 -->
        <property name="custName" column="custName"></property>

        <!-- 一方配置多方,映射外键 -->
        <!-- set标签表示多方 name属性: set集合名称 inverse属性: 是否放弃对关系的维护 true: 放弃关系的维护(在一对多时最好放弃一方的,应为一方维护一次就要为多方产生和数据相同都的sql update语句,影响性能) false: 不放弃关系的维护 (默认值) cascade属性: 级联操作。 操作一方,关联的另一方也做相同的操作,一般在<one-to-one>和<one-to-many>中设置级联 save-update: 级联保存和更新 delete: 级联删除 all: save-update+delete: 级联保存,更新,删除 -->
        <set name="linkMans" inverse="true" cascade="delete">
            <!-- hibernate机制:双向维护外键,一方和多方都配置外键 column属性:外键名称 -->
            <key column="clid"></key>
            <one-to-many class="entity.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>

LinkMan.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>
    <class name="entity.LinkMan" table="t_linkman">
        <id name="lid" column="lid">
            <generator class="native"></generator>
        </id>
        <property name="lkmName" column="lkmName"></property>
        <!-- 多方中配置一方 -->
        <many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>
    </class>
</hibernate-mapping>

对于inverse属性:
一对多表的关系在于多的那个表里有一个外键。在这里就是说,联系人表里面有一个外键是指向客户表的,这个外键就是两个表的关系,我们说的维护这个关系就是维护这个外键。
在更新客户表时,如果一方不放弃维护关系,在一方表更新后,会主动去update多方表,修改其外键,所以就有了如下的update语句;如果一方放弃维护关系,则不会有这条update语句,即不会主动去修改多方表的外键:

Hibernate: update t_customer set custName=?,custLevel=?,custSource=?,custPhone=?,custMobile=? where cid=? Hibernate: update t_linkman set clid=null where clid=?

第三步 将映射文件添加到核心配置文件中,我是把对hibernate的配置放到了spring配置文件中。

bean.xml

<!-- 配置hibernate基本信息 -->
<property name="hibernateProperties">
    <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
    </props>
</property>

<!-- 配置映射文件 .hbm.xml -->
<property name="mappingResources">
    <list>
        <value>entity/Customer.hbm.xml</value>
        <value>entity/LinkMan.hbm.xml</value>
    </list>
</property>