Hibernate映射关系之一对多/多对一(二)

一对多的关系,这里通过客户和联系人两个实体来演示:
1、数据库设计字段


一对多

2、实体关系


实体关系.png

3、建表
customer表:
DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer` (
  `cus_id` bigint(32) NOT NULL AUTO_INCREMENT,
  `cus_name` varchar(32) NOT NULL,
  `cus_mobile` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`cus_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

linkman表:

DROP TABLE IF EXISTS `linkman`;
CREATE TABLE `linkman` (
  `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT,
  `lkm_name` varchar(32) NOT NULL,
  `lkm_sex` char(1) DEFAULT NULL,
  `lkm_phone` varchar(16) DEFAULT NULL,
  `lkm_cus_id` bigint(32) DEFAULT NULL,
  PRIMARY KEY (`lkm_id`),
  KEY `fk_cus_lkm` (`lkm_cus_id`),
  CONSTRAINT `fk_cus_lkm` FOREIGN KEY (`lkm_cus_id`) REFERENCES `customer` (`cus_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

4、实体与实体映射文件的编写(不要忘记把实体映射文件放置到hibernate.cfg.xml文件中去)
Customer.java

package com.nieshenkuan.model;

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

public class Customer {
//  CREATE table customer(
//          cus_id BIGINT(32) PRIMARY KEY auto_increment,
//          cus_name VARCHAR(32) NOT NULL,
//          cus_mobile VARCHAR(32) DEFAULT NULL,

//          )ENGINE=INNODB CHARSET=utf8;
    private Long cus_id;
    private String cus_name;
    private String cus_mobile;

    private Set<LinkMan> linkMen=new HashSet<>();
    
    
    public Long getCus_id() {
        return cus_id;
    }
    public void setCus_id(Long cus_id) {
        this.cus_id = cus_id;
    }
    public String getCus_name() {
        return cus_name;
    }
    public void setCus_name(String cus_name) {
        this.cus_name = cus_name;
    }
    public String getCus_mobile() {
        return cus_mobile;
    }
    public void setCus_mobile(String cus_mobile) {
        this.cus_mobile = cus_mobile;
    }
    
    public Set<LinkMan> getLinkMen() {
        return linkMen;
    }
    public void setLinkMen(Set<LinkMan> linkMen) {
        this.linkMen = linkMen;
    }
    
    
}

Customer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-12-28 11:22:51 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.nieshenkuan.model">
    <class name="Customer" table="customer" lazy="true">
        <id name="cus_id" >
            <column name="cus_id"></column>
            <generator class="native"></generator>
        </id>
        <property name="cus_name"></property>
        <property name="cus_mobile"></property>
        <!-- 
            级联配置
            cascade:
            save-update   保存-更新
            delete        删除
            all          save-update+delete
         -->
        <set name="linkMen" table="linkman" cascade="all" inverse="true" lazy="true" fetch="subselect">
            <key>
                <column name="lkm_cus_id"></column>
            </key>
            <one-to-many class="LinkMan"/>
        </set>
    </class>
</hibernate-mapping>

LinkMan.java

package com.nieshenkuan.model;

public class LinkMan {
//  CREATE TABLE linkman(
//          lkm_id BIGINT(32) PRIMARY KEY auto_increment,
//          lkm_name VARCHAR(32) NOT NULL,
//          lkm_sex CHAR(1),
//          lkm_phone VARCHAR(16),
//          lkm_cus_id BIGINT(32),
//          CONSTRAINT fk_cus_lkm FOREIGN KEY(lkm_cus_id) REFERENCES customer(cus_id)
//          )ENGINE=INNODB CHARSET=utf8;
    private Long lkm_id;
    private String lkm_name;
    private Character lkm_sex;
    private String lkm_phone;
    private Customer customer;
    public Long getLkm_id() {
        return lkm_id;
    }
    public void setLkm_id(Long lkm_id) {
        this.lkm_id = lkm_id;
    }
    public String getLkm_name() {
        return lkm_name;
    }
    public void setLkm_name(String lkm_name) {
        this.lkm_name = lkm_name;
    }
    public Character getLkm_sex() {
        return lkm_sex;
    }
    public void setLkm_sex(Character lkm_sex) {
        this.lkm_sex = lkm_sex;
    }
    public String getLkm_phone() {
        return lkm_phone;
    }
    public void setLkm_phone(String lkm_phone) {
        this.lkm_phone = lkm_phone;
    }
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    
    
}

LinkMan.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-12-28 11:28:55 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.nieshenkuan.model">
    <class name="LinkMan" table="LINKMAN">
        <id name="lkm_id" >
            <column name="LKM_ID" />
            <generator class="native" />
        </id>
        <property name="lkm_name" type="java.lang.String">
            <column name="LKM_NAME" />
        </property>
        <property name="lkm_sex" type="java.lang.Character">
            <column name="LKM_SEX" />
        </property>
        <property name="lkm_phone" type="java.lang.String">
            <column name="LKM_PHONE" />
        </property>
        <!-- 
            lazy:
            false:立即加载
            proxy:代理,由其他元素决定
            fetch:
            select 单表查询
            join 多表查询
         -->
        <many-to-one name="customer" column="lkm_cus_id" class="Customer" lazy="proxy"  fetch="join"></many-to-one>
    </class>
</hibernate-mapping>

5、测试


    /**
     * 添加数据
     */
    @Test
    public void testOneToMany() {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        // ---------------------------------------------
        Customer customer = new Customer();
        customer.setCus_name("阿里巴巴");

        LinkMan linkMan = new LinkMan();
        linkMan.setLkm_name("马云");

        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("基哥");

        customer.getLinkMen().add(linkMan);
        customer.getLinkMen().add(linkMan1);
        linkMan.setCustomer(customer);
        linkMan1.setCustomer(customer);

        session.save(customer);
        session.save(linkMan);
        session.save(linkMan1);

        // ----------------------------------------------
        transaction.commit();
        session.close();
    }
/**
     * 查找数据
     */
    @Test
    public void deleteOneToMany2() {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        // ---------------------------------------------
        // 从cutomer对象查到linkman对象
        Customer cus = session.get(Customer.class,1L);
        System.out.println(cus);
        Set<LinkMan> set = cus.getLinkMen();
        if (set.isEmpty()) {
            System.out.println("set is null");

        } else {
            System.out.println("set is not null");
            for (LinkMan obj : set) {
                System.out.println(obj);
                System.out.println(obj.getLkm_id() + ":" + obj.getLkm_name() + ":" + obj.getCustomer().getCus_id());
            }
        }

        // 也能从linkman对象查到customer对象
        LinkMan linkMan = session.get(LinkMan.class, 2l);
        System.out.println(linkMan.getCustomer().getCus_name());

        // ----------------------------------------------
        transaction.commit();
        session.close();
    }

总结

总结:这种一对多的形式,是双向的,即从customer中能得到linkman,也能从linkman中得到customer。
一对多需要建立一个外键,(外键是在多的一方建立的),指向一的一方。
一的一方的实体中要有一个集合放置多的一方的对象,多的一方中的实体要包括一个一的一方的实体对象。

来看一下一的一方的配置文件(实体映射文件):
<set name="linkMen" table="linkman" cascade="all" inverse="true" lazy="true" fetch="subselect">
            <key>
                <column name="lkm_cus_id"></column>
            </key>
            <one-to-many class="LinkMan"/>
        </set>
详解:set中的name是对应customer中set集合的名字,table对应的是set对象表名(即多的一方在数据中的中表名)。
key:是代表外键
one-to-many中的class是对应多的一方的实体的名字。

接下来看一下多的一方的配置文件:
 <many-to-one name="customer" column="lkm_cus_id" class="Customer" lazy="proxy"  fetch="join">
</many-to-one>

详解:many-to-one,中的to-one ,就是指一的一方,这里的name就是填写一的一
方的字段名,在多的一方实体里面有一个一的一方的一个对象,就是这个对象名。
然后column是指多的一方在数据库表中的外键,通过这个将两个表连接起来的,很重要。
其次就是class是指to—one的一方的实体名。(并不是对象名)。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容