hibernate中的集合类标签

 

List是一个有序集合,所以当其生成简单表的时候,需要指定其下标(通过list-index标签),并且需要指定其表的名字。List所对应的表中以一个外键和下标作为联合主键。

一个简单的例子,list中存储的是简单的数据类型:

建立表的时候用的SQL语句:

//移除外键关系,防止删除的时候禁止删除

alter table children drop foreign key FK62EA5DFF7EA87F47

//如果存在parentchildren表,则删除

drop table if exists children

drop table if exists parent

//新建一个children

create table children (id integer not null, name varchar(255), num integer not null, primary key (id, num))

//新建一个parent

create table parent (id integer not null, age integer, name varchar(255), primary key (id))

//list表添加一个一个索引序列,并且增加了一个外键约束

alter table children add index FK62EA5DFF7EA87F47 (id), add constraint FK62EA5DFF7EA87F47 foreign key (id) references parent (id)

<!-- 该类中的list作为一个表存储的,需要指定其表的名字 -->

<list name="children" table="children">

       <!-- id指的是children中的外键,也就是标识该记录属于哪一个 -->

       <key column="id"/>

       <!-- 这个是有序表的下标,从另一个角度而言,也可以唯一的确定某一个元素 -->      

       <list-index column="num"/>

       <!-- 表中的元素,有且只有一个元素 -->

       <element type="string" column="name"/>

</list>

一个简单的插入测试

Hibernate: select max(id) from parent

Hibernate: insert into parent (age, name, id) values (?, ?, ?)

Hibernate: insert into children (id, num, name) values (?, ?, ?)

Hibernate: insert into children (id, num, name) values (?, ?, ?)

Hibernate: insert into children (id, num, name) values (?, ?, ?)

 

Set

list的差别就在于set是一个无序的集合,所以它不需要存储下标,即需不要list-index标签。一般而言自动生成的表是不带主键的,但是如果element元素设置为not-null则会将set中的元素和外键联合作为主键(但是,一般而言没有这个必要的,因为当数据量很大的时候,主键并不能起多大作用)。

建表SQL语句和list一样:

alter table children drop foreign key FK62EA5DFFFA0F22FC

drop table if exists children

drop table if exists parent

create table children (parent_id integer not null, name varchar(255))

create table parent (id integer not null, age integer, name varchar(255), primary key (id))

alter table children add index FK62EA5DFFFA0F22FC (parent_id), add constraint FK62EA5DFFFA0F22FC foreign key (parent_id) references parent (id)

<set name="children" table="children">

       <!-- 集合属性的外键列 -->

       <key column="parent_id"/>

       <!-- 集合属性中的元素 -->

       <element type="string" column="name"/>

</set>

插入测试:

Hibernate: select max(id) from parent

Hibernate: insert into parent (age, name, id) values (?, ?, ?)

Hibernate: insert into children (parent_id, name) values (?, ?)

Hibernate: insert into children (parent_id, name) values (?, ?)

Hibernate: insert into children (parent_id, name) values (?, ?)

Bag

Bag元素可以为所有实现Collection接口的类进行属性映射,并且将其映射为无序集合,并且集合对应的表没有主键。其形式和set及其类似。

建表语句和listset一样:

alter table children drop foreign key FK62EA5DFFA72135C8

drop table if exists children

drop table if exists parent

create table children (person_num integer not null, name varchar(255))

create table parent (id integer not null, age integer, name varchar(255), primary key (id))

alter table children add index FK62EA5DFFA72135C8 (person_num), add constraint FK62EA5DFFA72135C8 foreign key (person_num) references parent (id)

<bag name="children">

       <key column="person_num"/>

       <element type="string" column="name"/>

</bag>

插入测试:

Hibernate: select max(id) from parent

Hibernate: insert into parent (age, name, id) values (?, ?, ?)

Hibernate: insert into children (person_num, name) values (?, ?)

Hibernate: insert into children (person_num, name) values (?, ?)

Hibernate: insert into children (person_num, name) values (?, ?)

Map

Map对应于java中的map接口,那么它存储的内容无意就是键-值信息了,外加一个外键。显然,它是将mapkey和外键联合起来作为主键的。

生成的建表语句:

alter table children drop foreign key FK62EA5DFF9987B23F

drop table if exists children

drop table if exists parent

create table children (parent_map_id integer not null, sex varchar(255), name varchar(255) not null, primary key (parent_map_id, name))

create table parent (id integer not null, age integer, name varchar(255), primary key (id))

alter table children add index FK62EA5DFF9987B23F (parent_map_id), add constraint FK62EA5DFF9987B23F foreign key (parent_map_id) references parent (id)

<map name="children">

       <!-- 映射外键 -->

       <key column="parent_map_id"/>

       <!-- mapkey -->

       <map-key type="string" column="name"/>

       <!-- mapvalue -->

       <element type="string" column="sex"/>

</map>

插入测试:

Hibernate: select max(id) from parent

Hibernate: insert into parent (age, name, id) values (?, ?, ?)

Hibernate: insert into children (parent_map_id, name, sex) values (?, ?, ?)

Hibernate: insert into children (parent_map_id, name, sex) values (?, ?, ?)

Hibernate: insert into children (parent_map_id, name, sex) values (?, ?, ?)

总结:

集合名字

标签名

备注

List

<list>

需要指定下标标签,其主键为:外键和下标联合形成

Set

<set>

如果<element>元素的not-null属性设置为true,则将外键和element内容联合设置为主键,否则没有主键

Collection

<bag>

没有主键

Map

<map>

其中map-keynot-null属性默认值为true,其主键为map的键值和外键联合组成的

性能对比总结:

当集合中元素内容很多很多的时候(例如十万),在初始化持久化类的时候,要完成所有集合属性的加载,势必将导致性能急剧下降。所以就产生了延迟加载策略:lazy=”true”

无序、有序集合的优缺点:

有序集合由<key><index>组成的联合主键,在这种情况下,集合属性的更新是非常高效的(主键已经被有效的索引)。

无序集合中,如果<element>元素设置为非空,那么也会有主键,但是如果此时<element>元素是组合元素或者为大量文本、二进制字段,那么数据库的主键就显得那么的庞大,使得检索性能变得很差。

 

=====================================

复杂类型的映射:

当一个模型中有一些属性为复杂类型的时候(例如是一个类的实例),需要用到<component>标签。此标签只是将一个表中某些耦合度很强的内容写在另一个类中,但是表现到数据库中仍和其他属性在一个表中。

其建表语句为:

drop table if exists parent

create table parent (id integer not null, age integer, name varchar(255), first varchar(255), last varchar(255), primary key (id))

<!-- 特别的,此处需要指定class属性,unique属性不是强制性的设置为ture,二十根据实际情况设定 -->

<component name="component" class="com.dong.model.Name" unique="true">

       <!-- 罗列出Name中的所有变量,并将其映射到数据库中的属性列 -->

       <property name="firstName" column="first"/>

       <property name="lastName" column="last"/>

</component>

那么如果集合中的属性为复杂属性的时候,需要做怎样的配置呢,其实也很简单的,只是将配置文件进行修改即可:

<set name="children" table="children">

       <!-- 集合属性的外键列 -->

       <key column="parent_id"/>

       <!-- 集合属性中的元素 -->

       <composite-element class=”com.dong.model.Name”>

              <!—映射每一个属性 -->

              <property name=”firstName”/>

              <property name=”lastName”/>

       <composite-element>

</set>

那么如果一个模型的主键为一个复杂属性的时候,又需要做如何的配置呢,也很简单,只需要用<composite-id>代替<id>即可。但是需要注意的是,作为主键的复杂属性所对应的类必须要重写equals()hashCode()方法,并且要实现serializable接口,其实这个原因也很容易想得到:重写那两个方法,只是为了确定主键的唯一性,实现比较对比;实现serializable接口是为了方便其存储到文件中,并且当从数据库中按照主键读取内容是,需要传递该类的一个实例(必须给主键赋值),也就是get的第二个实现serializable的参数。

下面是他的配置:

<class name=”com.dong.model.Person” table=”person”>

       <!—此标签的功能就相当于id标签的功能 -->

       <composite-id name=”name” class=”com.dong.model.Name”>

              <!—Name类中的所有变量映射到表中的属性列 -->

              <key-property name=”firstName”/>

              <key-property name=”firstName”/>

       </composite-id>

</class>

注意:hibernate是不推荐使用此方法的,因为主键越复杂,那么使得表的检索变得越困难,而且此处是使用的是联合主键使得检索变得更加的困难。

当然,如果模型的主键为一个复杂属性的时候,也可以将其复杂属性写在模型类中,没有必要新建一个类存储,但是也需要重写equals()hashCode()方法,并且仍然需要实现serializable接口,但是在equals方法和hashCode方法中只需要操作、判断将要作为主键的变量即可,无需考虑其它的变量,原因也显然而知,主键就是用来决定表的唯一性。

其配置文件和上面的那个及其相似,但是不需要为<composite-id>标签指定nameclass属性:

<class name=”com.dong.model.Person” table=”person”>

       <!—此标签的功能就相当于id标签的功能 -->

       <composite-id>

              <!—Name类中的所有变量映射到表中的属性列 -->

              <key-property name=”firstName”/>

              <key-property name=”firstName”/>

       </composite-id>

</class>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wlzjdm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值