hibernate 映射关系—关系映射(一对多)

一对多关联关系是数据库表格关系中最常用的关联关系,有很多例子,比如顾客和订单的关系,下面来学习hibernate中一对多的实现。
1、数据库设计

CREATE TABLE `customer` (
  `cid` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `phone` varchar(11) NOT NULL,
  `address` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `register_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`cid`),
  UNIQUE KEY `AK_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

CREATE TABLE `orders` (
  `oid` bigint(20) NOT NULL AUTO_INCREMENT,
  `cid` bigint(20) NOT NULL,
  `price` double NOT NULL,
  `name` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`oid`),
  KEY `fk_cid` (`cid`),
  CONSTRAINT `fk_cid` FOREIGN KEY (`cid`) REFERENCES `customer` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

2、配置文件

<hibernate-mapping package="com.study.hibernate.hbm">
    <class name="Customer" table="customer" catalog="hibernate">
        <id name="cid" type="java.lang.Long">
            <column name="cid" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="name" length="64" not-null="true" unique="true" />
        </property>
        <property name="phone" type="string">
            <column name="phone" length="11" not-null="true" />
        </property>
        <property name="address" type="string">
            <column name="address" length="256" not-null="true" />
        </property>
        <property name="registerTime" type="timestamp">
            <column name="register_time" length="19" not-null="true" />
        </property>
        <set name="orderses" table="orders" inverse="true" lazy="true" fetch="select">
            <key>
                <column name="cid" not-null="true" />
            </key>
            <one-to-many class="Orders" />
        </set>
    </class>
</hibernate-mapping>

<hibernate-mapping package="com.study.hibernate.hbm">
    <class name="Orders" table="orders" catalog="hibernate">
        <id name="oid" type="java.lang.Long">
            <column name="oid" />
            <generator class="identity" />
        </id>
        <many-to-one name="customer" class="Customer" fetch="select">
            <column name="cid" not-null="true" />
        </many-to-one>
        <property name="price" type="double">
            <column name="price" precision="22" scale="0" not-null="true" />
        </property>
        <property name="name" type="string">
            <column name="name" length="256" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

3、持久化类

public class Customer implements java.io.Serializable {

    private Long cid;
    private String name;
    private String phone;
    private String address;
    private Date registerTime;
    private Set orderses = new HashSet(0);
}
public class Orders implements java.io.Serializable {

    private Long oid;
    private Customer customer;
    private double price;
    private String name;
}

4、关键点总结
延迟加载方面
1)使用lazy和fetch两个字段来配置延迟加载,这里的延迟加载不是说load的延迟加载,而是指关联对象的延迟加载
2)lazy=false方式对createQuery和get操作方式有效,fetch=join的方式只对get方式的操作有效
3)当fetch=join时,若连接的表层级太深,可能影响性能,这个可以在Hibernate属性文件中设置max_fetch_depth属性来控制连接的层级数。
4)非延迟加载时,没有设置batch-size,当使用find查找Customer,Order的获取是每个Customer都会发出一条sql语句进行查找,若设置batch-size,则会优化Orders的sql查找为in的情况,即减少sql语句的条数,该属性只能用在一端的配置中,即集合配置中。

级联操作方面
1)一端save时可以单独保存,也可以级联保存多端的数据,只需设置cascade的属性为save-update或以上;多端save时需要注意,由于外键约束的原因,多端保存时一端要么在数据库中有相应的记录,要么多端级联同时保存一端,级联配置也很简单,只需要配置cascade的属性为save-update或以上
2)由于外键约束一端delete时必须设置delete操作的级联属性cascade=all或以上;多端delete时一般不需要级联处理,只需删除自身就ok
3)更新一端时会同时更新多端的数据;更新多端时若只是基本信息对一端没有影响,若是更新关联的一端,则需要同时更新新的一端(若新的一端之前还有相应的多端时,还需更新多端)即至少2条update语句,其他的update语句根据新的一端相应的多端数据记录来决定;最后还有一种情况需要注意,即一端先remove多端的某个对象,再update一端时,若需要在数据库中删除remove的多端对象,需要设置cascade=all-delete-orphan,否则不会级联删除
4)当casecade=all,则是支持save-update和delete的关联操作。而cascade=all-delete-orphan一般用于set中,作用是在解除父子关系时,自动删除不属于父对象的子对象, 也支持级联删除和级联保存更新,比如如下代码,提交时会删除order记录。customer.getOrders().removre(order),order.setCustomer(null),tx.commit();

inverse
inverse的意思是反转,反转什么呢,这里是指反转维护关联关系变化的权利,若inverse=true则说明维护关联关系变化的权利反转,交给对方来处理,一般one端不维护关联关系都是交个many端来维护即设置inverse=true,在many-to-one中inverse不支持配置,默认即处理关联关系的变化。
比如,当inverse=true时,往Customer添加order然后保存customer时,只会有insert语句;inverse=false,则表示感应对象更新关系的变化,当往customer添加order然后保存customer时,不但有insert语句,还有update语句,明显这个时候的update是多余的。

单向和双向
单向和双向一般应该根据业务的需要来设置,单向无非就是在双向的基础上去掉某一端的关联关系配置,使得变成单向关联,具体就不细说了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值