Hibernate基于配置文件的一对多级联CRUD操作

1.建立客户表和联系人表,客户和联系人是一对多关系,联系人中有一个lkm_cst_id外键

CREATE TABLE `cst_customer` (
  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
  `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
  `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
  `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
  `cust_address` varchar(128) DEFAULT NULL COMMENT '客户联系地址',
  `cust_phone` varchar(64) DEFAULT NULL COMMENT '客户联系电话',
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
CREATE TABLE `cst_linkman` (
  `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
  `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
  `lkm_gender` varchar(10) DEFAULT NULL COMMENT '联系人性别',
  `lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
  `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',
  `lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
  `lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',
  `lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',
  `lkm_cst_id` bigint(32) NOT NULL,
  PRIMARY KEY (`lkm_id`),
  KEY `FK3deqymsc65sso3qdslytwk20r` (`lkm_cst_id`),
  CONSTRAINT `FK3deqymsc65sso3qdslytwk20r` FOREIGN KEY (`lkm_cst_id`) REFERENCES `cst_customer` (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

2.编辑cfg.xml配置文件

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!--1.连接数据库的信息-->
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <!--2.hibernate可选配置-->
        <!--检测实体类的映射配置和数据库的表结构是否一致,如果不一致,更新表结构-->
        <property name="hbm2ddl.auto">update</property>
        <!--数据库方言-->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <!--是否显示hibernate生成的sql语句-->
        <property name="hibernate.show_sql">true</property>
        <!--是否使用格式化输出sql语句-->
        <property name="hibernate.format_sql">true</property>
        <!--3.设置hibernate的连接池提供商-->
        <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>

        <!--4.映射文件的位置-->
        <mapping class="domain.CstCustomerEntity"/>
        <mapping resource="domain/CstCustomerEntity.hbm.xml"/>
        <mapping class="domain.CstLinkmanEntity"/>
        <mapping resource="domain/CstLinkmanEntity.hbm.xml"/>
        <!-- DB schema will be updated if needed -->
        <!-- <property name="hbm2ddl.auto">update</property> -->
    </session-factory>
</hibernate-configuration>

3.使用idea反向映射,生成实体类和hbm映射文件,并在客户表中用Set表示联系人,在联系人表中使用Customer对象表示客户

    客户实体

package domain;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * @Author: David.Xiao
 * @Date: 2018/11/10 18:48
 * @Description:
 */
@Entity
@Table(name = "cst_customer", schema = "hibernate", catalog = "")
public class CstCustomerEntity {
    private long custId;
    private String custName;
    private String custSource;
    private String custIndustry;
    private String custLevel;
    private String custAddress;
    private String custPhone;
    
    private Set<CstLinkmanEntity> cstLinkmanEntitySet = new HashSet<>(0);
    public Set<CstLinkmanEntity> getCstLinkmanEntitySet() {
        return cstLinkmanEntitySet;
    }

    public void setCstLinkmanEntitySet(Set<CstLinkmanEntity> cstLinkmanEntitySet) {
        this.cstLinkmanEntitySet = cstLinkmanEntitySet;
    }

    @Id
    @Column(name = "cust_id")
    public long getCustId() {
        return custId;
    }

    public void setCustId(long custId) {
        this.custId = custId;
    }

    @Basic
    @Column(name = "cust_name")
    public String getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }

    @Basic
    @Column(name = "cust_source")
    public String getCustSource() {
        return custSource;
    }

    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }

    @Basic
    @Column(name = "cust_industry")
    public String getCustIndustry() {
        return custIndustry;
    }

    public void setCustIndustry(String custIndustry) {
        this.custIndustry = custIndustry;
    }

    @Basic
    @Column(name = "cust_level")
    public String getCustLevel() {
        return custLevel;
    }

    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }

    @Basic
    @Column(name = "cust_address")
    public String getCustAddress() {
        return custAddress;
    }

    public void setCustAddress(String custAddress) {
        this.custAddress = custAddress;
    }

    @Basic
    @Column(name = "cust_phone")
    public String getCustPhone() {
        return custPhone;
    }

    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CstCustomerEntity that = (CstCustomerEntity) o;
        return custId == that.custId &&
                Objects.equals(custName, that.custName) &&
                Objects.equals(custSource, that.custSource) &&
                Objects.equals(custIndustry, that.custIndustry) &&
                Objects.equals(custLevel, that.custLevel) &&
                Objects.equals(custAddress, that.custAddress) &&
                Objects.equals(custPhone, that.custPhone);
    }

    @Override
    public int hashCode() {

        return Objects.hash(custId, custName, custSource, custIndustry, custLevel, custAddress, custPhone);
    }

    @Override
    public String toString() {
        return "CstCustomerEntity{" +
                "custId=" + custId +
                ", custName='" + custName + '\'' +
                ", custSource='" + custSource + '\'' +
                ", custIndustry='" + custIndustry + '\'' +
                ", custLevel='" + custLevel + '\'' +
                ", custAddress='" + custAddress + '\'' +
                ", custPhone='" + custPhone + '\'' +
                '}';
    }
}

    客户hbm映射文件,配置set标签,并根据情况添加inverse和cascade配置

<?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="domain">

    <class name="CstCustomerEntity" table="cst_customer" schema="hibernate">
        <id name="custId" column="cust_id">
            <generator class="increment"></generator>
        </id>
        <property name="custName" column="cust_name"/>
        <property name="custSource" column="cust_source"/>
        <property name="custIndustry" column="cust_industry"/>
        <property name="custLevel" column="cust_level"/>
        <property name="custAddress" column="cust_address"/>
        <property name="custPhone" column="cust_phone"/>

        <!--一对多关系映射-->
        <!--set:配置set集合  name:实体中set集合名称  table:从表名称,在一对多配置时可以不写-->
        <!--级联操作时要设置cascade属性,级联更新保存设置为save-update、级联删除时设置为delete-->
        <set name="cstLinkmanEntitySet" table="cst_linkman" inverse="true" cascade="save-update,delete">
            <!--key:配置外键字段  column:从表中外键字段名-->
            <key column="lkm_cst_id"></key>
            <!--one-to-many:建立一对多的映射配置 class:从表实体类名称 -->
            <one-to-many class="CstLinkmanEntity"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

    联系人实体

package domain;

import javax.persistence.*;
import java.util.Objects;

/**
 * @Author: David.Xiao
 * @Date: 2018/11/10 18:48
 * @Description:
 */
@Entity
@Table(name = "cst_linkman", schema = "hibernate", catalog = "")
public class CstLinkmanEntity {
    private long lkmId;
    private String lkmName;
    private String lkmGender;
    private String lkmPhone;
    private String lkmMobile;
    private String lkmEmail;
    private String lkmPosition;
    private String lkmMemo;
    private long lkmCstId;

    private CstCustomerEntity cstCustomerEntity = new CstCustomerEntity();
    public CstCustomerEntity getCstCustomerEntity() {
        return cstCustomerEntity;
    }
    public void setCstCustomerEntity(CstCustomerEntity cstCustomerEntity) {
        this.cstCustomerEntity = cstCustomerEntity;
    }

    @Id
    @Column(name = "lkm_id")
    public long getLkmId() {
        return lkmId;
    }

    public void setLkmId(long lkmId) {
        this.lkmId = lkmId;
    }

    @Basic
    @Column(name = "lkm_name")
    public String getLkmName() {
        return lkmName;
    }

    public void setLkmName(String lkmName) {
        this.lkmName = lkmName;
    }

    @Basic
    @Column(name = "lkm_gender")
    public String getLkmGender() {
        return lkmGender;
    }

    public void setLkmGender(String lkmGender) {
        this.lkmGender = lkmGender;
    }

    @Basic
    @Column(name = "lkm_phone")
    public String getLkmPhone() {
        return lkmPhone;
    }

    public void setLkmPhone(String lkmPhone) {
        this.lkmPhone = lkmPhone;
    }

    @Basic
    @Column(name = "lkm_mobile")
    public String getLkmMobile() {
        return lkmMobile;
    }

    public void setLkmMobile(String lkmMobile) {
        this.lkmMobile = lkmMobile;
    }

    @Basic
    @Column(name = "lkm_email")
    public String getLkmEmail() {
        return lkmEmail;
    }

    public void setLkmEmail(String lkmEmail) {
        this.lkmEmail = lkmEmail;
    }

    @Basic
    @Column(name = "lkm_position")
    public String getLkmPosition() {
        return lkmPosition;
    }

    public void setLkmPosition(String lkmPosition) {
        this.lkmPosition = lkmPosition;
    }

    @Basic
    @Column(name = "lkm_memo")
    public String getLkmMemo() {
        return lkmMemo;
    }

    public void setLkmMemo(String lkmMemo) {
        this.lkmMemo = lkmMemo;
    }

    @Basic
    @Column(name = "lkm_cst_id")
    public long getLkmCstId() {
        return lkmCstId;
    }

    public void setLkmCstId(long lkmCstId) {
        this.lkmCstId = lkmCstId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CstLinkmanEntity that = (CstLinkmanEntity) o;
        return lkmId == that.lkmId &&
                lkmCstId == that.lkmCstId &&
                Objects.equals(lkmName, that.lkmName) &&
                Objects.equals(lkmGender, that.lkmGender) &&
                Objects.equals(lkmPhone, that.lkmPhone) &&
                Objects.equals(lkmMobile, that.lkmMobile) &&
                Objects.equals(lkmEmail, that.lkmEmail) &&
                Objects.equals(lkmPosition, that.lkmPosition) &&
                Objects.equals(lkmMemo, that.lkmMemo);
    }

    @Override
    public int hashCode() {

        return Objects.hash(lkmId, lkmName, lkmGender, lkmPhone, lkmMobile, lkmEmail, lkmPosition, lkmMemo, lkmCstId);
    }

    @Override
    public String toString() {
        return "CstLinkmanEntity{" +
                "lkmId=" + lkmId +
                ", lkmName='" + lkmName + '\'' +
                ", lkmGender='" + lkmGender + '\'' +
                ", lkmPhone='" + lkmPhone + '\'' +
                ", lkmMobile='" + lkmMobile + '\'' +
                ", lkmEmail='" + lkmEmail + '\'' +
                ", lkmPosition='" + lkmPosition + '\'' +
                ", lkmMemo='" + lkmMemo + '\'' +
                ", lkmCstId=" + lkmCstId +
                '}';
    }
}

    联系人hbm映射文件,配置many-to-one标签,并根据情况配置cascade属性

<?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">
<!--package:导包,下面就不用再写全限定类名-->
<hibernate-mapping package="domain">

    <class name="CstLinkmanEntity" table="cst_linkman" schema="hibernate">
        <id name="lkmId" column="lkm_id">
            <generator class="increment"></generator>
        </id>
        <property name="lkmName" column="lkm_name"/>
        <property name="lkmGender" column="lkm_gender"/>
        <property name="lkmPhone" column="lkm_phone"/>
        <property name="lkmMobile" column="lkm_mobile"/>
        <property name="lkmEmail" column="lkm_email"/>
        <property name="lkmPosition" column="lkm_position"/>
        <property name="lkmMemo" column="lkm_memo"/>
        <!--<property name="lkmCstId" column="lkm_cst_id"/>-->

        <!--建立多对一的映射配置-->
        <!--name:引用的主表实体的对象的名称-->
        <!--class:引用的主表实体的类的名称-->
        <!--column:从表中外键字段的名称-->
        <many-to-one name="cstCustomerEntity" class="CstCustomerEntity" column="lkm_cst_id"></many-to-one>
    </class>
</hibernate-mapping>

4.写一对多的级联CRUD方法,直接操作java对象即可

package dao;

import domain.CstCustomerEntity;
import domain.CstLinkmanEntity;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import java.util.Set;

import static org.junit.Assert.*;

/**
 * @Author: David.Xiao
 * @Date: 2018/11/10 19:40
 * @Description:
 */
public class HibernateOne2ManyTest {

    @Test
    public void openSession() {
       Session session = HibernateUtil.openSession();
    }

    /**
     * 保存联系人
     * 创建一个新的联系人,需要关联一个客户
     */
    @Test
    public void saveLinkman()
    {
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();
        CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,1L);
        CstLinkmanEntity linkmanEntity = new CstLinkmanEntity();
        linkmanEntity.setCstCustomerEntity(customerEntity);
        linkmanEntity.setLkmName("张老五");
        session.save(linkmanEntity);
        tx.commit();
    }

    /**
     * 级联保存:在set或many-to-one标签中配置cascade属性
     * 保存有关联关系的两个表
     * 保存客户和联系人
     */
    @Test
    public void saveCascade()
    {
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();

        //1.创建客户
        CstCustomerEntity customerEntity = new CstCustomerEntity();
        customerEntity.setCustName("王老三");
        customerEntity.setCustSource("南京大学");
        customerEntity.setCustIndustry("阿里");
        customerEntity.setCustLevel("vip");
        customerEntity.setCustAddress("北京市海淀区");
        customerEntity.setCustPhone("132456789");
        //2.创建联系人
        CstLinkmanEntity linkmanEntity = new CstLinkmanEntity();
        linkmanEntity.setLkmName("王老三联系人");
        linkmanEntity.setLkmGender("男");
        linkmanEntity.setLkmPhone("132465789");
        linkmanEntity.setLkmMobile("321654987");
        linkmanEntity.setLkmEmail("[email protected]");
        linkmanEntity.setLkmPosition("北京市朝阳区");
        linkmanEntity.setLkmMemo("1");
        //3.建立客户和联系人之间的双向关系
        linkmanEntity.setCstCustomerEntity(customerEntity);
        customerEntity.getCstLinkmanEntitySet().add(linkmanEntity);

        //4.对哪个对象进行级联保存,就在哪个实体对应的hbm文件中,添加cascade属性
        //选择一个
        session.save(customerEntity);
        session.save(linkmanEntity);

        tx.commit();
    }


    /**
     * 级联更新
     * 查询一个客户,并给他添加一个新的联系人
     */
    @Test
    public void updateCascade()
    {
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();

        //1.创建客户
        CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,1L);
        //2.创建联系人
        CstLinkmanEntity linkmanEntity = new CstLinkmanEntity();
        linkmanEntity.setLkmName("李老大联系人2");
        linkmanEntity.setLkmGender("男");
        linkmanEntity.setLkmPhone("132465789");
        linkmanEntity.setLkmMobile("321654987");
        linkmanEntity.setLkmEmail("[email protected]");
        linkmanEntity.setLkmPosition("北京市朝阳区");
        linkmanEntity.setLkmMemo("1");
        //3.建立客户和联系人之间的双向关系
        linkmanEntity.setCstCustomerEntity(customerEntity);
        customerEntity.getCstLinkmanEntitySet().add(linkmanEntity);

        //4.对客户对象进行级联更新
        session.update(customerEntity);

        tx.commit();
    }

    /**
     * 查询一个客户,并删除(联系人中有对它的引用)
     *  普通删除:
     *      在删除时,hibernate会更新从表中的行,将这一行的外键设为null,然后删除主表中的行
     *      前提:外键字段不能设置非空
     *  级联删除:在set标签中配置cascade属性为delete
     *      外键字段没有非空限制:在删除时,hibernate会删除从表中的行,然后删除主表中的行
     *      外键字段有非空限制:仍然想级联删除,则要在set中配置inverse=true
     */
    @Test
    public void deleteCascade()
    {
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();

        //1.创建客户
        CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,4L);

        //2.对客户对象进行级联删除
        session.delete(customerEntity);

        tx.commit();
    }

    /**
     * 对象导航查询
     * hibernate中的查询方式:OID查询、HQL查询、QBC查询、SQL查询、对象导航查询
     * 通过调用getXXX方法查询
     *
     * 关于一对多的立即查询和延迟查询:
     *  class标签的lazy:load方法是否是延迟加载
     *  set标签的lazy:查询关联的集合对象是否是延迟加载
     *  many-to-one的lazy:查询关联的主表实体是否是立即加载
     */
    @Test
    public void queryCascade()
    {
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();

        //注意避免嵌套调用toString的问题
        //查询某客户对应的联系人
        CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,5L);
        Set<CstLinkmanEntity>  linkmanEntitySet = customerEntity.getCstLinkmanEntitySet();

        for (CstLinkmanEntity linkman:linkmanEntitySet) {
            System.out.println(linkman.toString());
        }

        //查询某联系人对应的客户
        CstLinkmanEntity linkmanEntity = session.get(CstLinkmanEntity.class,9L);
        CstCustomerEntity cstCustomerEntity = linkmanEntity.getCstCustomerEntity();
        System.out.println(cstCustomerEntity.toString());

        tx.commit();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_22339269/article/details/84023963