hibernate 映射关系—集合映射

1、集合映射简介

当持久化类中有一个值类型的集合,那么就需要一张额外的数据库表来保存这个值类型集合的数据,这张表被称为集合表。比如有一张学生表,学生可能有很多爱好,就需要一种学生爱好集合表来存储学生的爱好信息。
Hibernate支持大部分重要的JDK集合接口映射,主要有以下几种。
1. set
可以映射类型为java.util.Set接口的属性,它的元素存放没有顺序且不允许重复;也可映射类型为java.util.SortSet接口的属性。它的元素可以按自然顺序排列。
2. list
可以映射类型为java.util.List接口的属性,它需要在结合属性对应的数据库表中用一个额外的索引列保存每个元素的位置。
3. array
可以映射类型为数组的属性,也需要额外的索引机制支持,但它在实际运用中用得极少。
4. bag/idbag
可以映射类型为java.util.Collection接口的属性。它的元素可重复,但不保存顺序,不需要额外的索引支持。
5. map
可以映射类型为java.util.Map接口的属性,它的元素以键/值对的形式保存,也是无序的,也可以映射类型为java.util.SortMap接口的属性,它的元素可以按自然顺序排序。

2、集合映射使用

  1. 数据结构
CREATE TABLE `student` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `age` tinyint(4) NOT NULL,
  `sex` bit(1) NOT NULL,
  `address` varchar(128) NOT NULL,
  `cardid` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `student_hobby` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `StudentId` bigint(20) NOT NULL,
  `ListIndex` int(11) NOT NULL,
  `Description` varchar(256) DEFAULT NULL,
  `Times` int(11) DEFAULT NULL,
  `Level` int(11) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  KEY `fk_sid` (`StudentId`),
  CONSTRAINT `fk_sid` FOREIGN KEY (`StudentId`) REFERENCES `student` (`id`) ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
  • 配置文件
<hibernate-mapping package="com.study.hibernate.hbm">
    <class name="Student" table="student" catalog="hibernate">
        <id name="id" type="java.lang.Long">
            <column name="id" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="name" length="64" not-null="true" />
        </property>
        <property name="age" type="byte">
            <column name="age" not-null="true" />
        </property>
        <property name="sex" type="boolean">
            <column name="sex" not-null="true" />
        </property>
        <property name="address" type="string">
            <column name="address" length="128" not-null="true" />
        </property>
        <property name="cardid" type="string">
            <column name="cardid" length="128" not-null="true" />
        </property>
        <!-- 这里set的元素是一个实体,不是单个元素,需要注意composite-->
        <set name="setHobbies" table="student_hobby" lazy="false">
            <key column="StudentId" />
            <!--  <element column="Desc" type="string"/> -->
            <composite-element class="StudentHobbyComposite">
                <property name="times"></property>
                <property name="description"></property>
                <property name="level"></property>
            </composite-element>
        </set>

        <list name="listHobbies" table="student_hobby" lazy="false">  
            <key column="StudentId"/>  
            <list-index column="ListIndex" />  
            <element column="Description" type="string" />  
        </list> 

        <array name="arrayHobbies" table="student_hobby" cascade="persist">
            <key column="StudentId"/>
            <list-index column="ListIndex" />
            <element column="Description" type="string" />  
        </array>

        <bag name="bagHobbies" table="student_hobby" order-by="level asc" lazy="false">
            <key column="StudentId"/>
            <element column="Description" type="string"/>
        </bag>

        <map name="mapHobbies" table="student_hobby" lazy="false">  
            <key column="StudentId"/>  
            <map-key column="Id" type="java.lang.Integer" />  
            <element column="Description" type="string" />  
        </map>
    </class>
</hibernate-mapping>
  • 实体类结构
public class Student implements java.io.Serializable {

    private Long id;
    private String name;
    private byte age;
    private boolean sex;
    private String address;
    private String cardid;

    private Set setHobbies = new HashSet(0);
    private List listHobbies = new ArrayList(0);
    private Object arrayHobbies[] = new Object[0];
    private List bagHobbies = new ArrayList(0);
    private Map mapHobbies = new HashMap(0);

    // 省略get/set方法
}
public class StudentHobbyComposite {
    private Integer id;
    private String description;
    private Integer times;
    private Integer level;

    // 省略get/set方法,
    // equal和hashcode方法必须重写
}

3、使用问题集合

  • composite-element对应的实例类equal和hashcode方法
    composite-element对应的实体类,必须重写equal和hashcode方法,不然作为set元素存储时会每次都会当做一个新的对象,导致每次get时都会对集合表先执行一次delete操作,然后再执行insert操作。

  • list/array base的使用
    list/array的起始下标是0,这个需要注意,若集合表中的Index的起始位置不是0,则会导致list/array中有NULL元素的问题,这个时候我们可以使用base来同步集合表中Index的下标,或者集合表中Index的下标记得从0开始。

  • 与关系映射的一点点区别
    使用集合映射的时候,我们发现和关系映射中使用set/list等属性是差不多的,关系映射中单向一对多的情况,和集合映射是一样的,唯一的区别就是使用集合映射时集合表是不需要配置文件的,但是关系映射时这个多的一方必须有配置文件,这个可能是和单向一对多关系映射中最大的区别。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值