欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java的Hibernate框架中集合类数据结构的映射编写教程

程序员文章站 2024-03-13 12:44:27
一、集合映射 1.集合小介 集合映射也是基本的映射,但在开发过程中不会经常用到,所以不需要深刻了解,只需要理解基本的使用方法即可,等在开发过程中遇到了这种问题时能够查询...

一、集合映射

1.集合小介
集合映射也是基本的映射,但在开发过程中不会经常用到,所以不需要深刻了解,只需要理解基本的使用方法即可,等在开发过程中遇到了这种问题时能够查询到解决方法就可以了。对应集合映射它其实是指将java中的集合映射到对应的表中,是一种集合对象的映射,在java中有四种类型的集合,分别是set、map、list还有普通的数组,它们之间有很大的区别:
(1)set,不可以有重复的对象,对象是无序的;
(2)list,可以与重复的对象,对象之间有顺序;
(3)map,它是键值成对出现的;
(4)数组,可以重复,对象之间有顺序。
它们之间的区别决定了在开发时使用哪种集合,通常在开发时会使用set,它内部的对象是无需的,并可以使用迭代器获取内部对象。这几种集合想要映射到相应的关系模型的话就必须使用hibernate提供的映射标签,<set>、<list>、<map>、<array>。

2.映射小介
继续讨论集合映射的关系模型,集合映射是指一个对象对应着另一个对象集合,在保存时hibernate会把数据集合保存到相应的表中,并按照自己分配的id把数据保存到数据表中,如果单独为集合分配了新表,那么会将id分配给集合表的id,那么对应的关系表如下图:

Java的Hibernate框架中集合类数据结构的映射编写教程

3.类文件
集合映射是如何通过代码实现的,接下来具体分析。这里把所有的集合封存到一个类中,这个类我们称之为collectionmapping.java,那么它对应的内部代码如下:

package com.hibernate; 
 
import java.util.list; 
import java.util.map; 
import java.util.set; 
 
@suppresswarnings("rawtypes") 
public class collectionmapping { 
   
  //id 
  private int id; 
  public int getid() { 
    return id; 
  } 
  public void setid(int id) { 
    this.id = id; 
  } 
   
  //名字 
  private string name; 
  public string getname() { 
    return name; 
  } 
  public void setname(string name) { 
    this.name = name; 
  } 
   
  //set集合 
  private set setvalues; 
  public set getsetvalues() { 
    return setvalues; 
  } 
  public void setsetvalues(set setvalues) { 
    this.setvalues = setvalues; 
  } 
   
  //list集合 
  private list listvalues; 
  public list getlistvalues() { 
    return listvalues; 
  } 
  public void setlistvalues(list listvalues) { 
    this.listvalues = listvalues; 
  } 
   
  //数组集合 
  private string[] arrayvalues; 
  public string[] getarrayvalues() { 
    return arrayvalues; 
  } 
  public void setarrayvalues(string[] arrayvalues) { 
    this.arrayvalues = arrayvalues; 
  } 
   
  //map集合 
  private map mapvalues; 
  public map getmapvalues() { 
    return mapvalues; 
  } 
  public void setmapvalues(map mapvalues) { 
    this.mapvalues = mapvalues; 
  } 
} 

该类中封装了几种常用的集合,想要转化为关系模型,就必须来看下文的映射。

4.集合映射
集合的映射其实相当的简单,只需要添加对应的集合标签,hibernate分别提供了集合标签<set>、<map>、<list>、<array>,通过使用集中标签来将集合映射为对应的关系表,另外通过添加<key>标签来实现表外键的关联,其它的属性通过使用<element>来添加。
collectionmapping.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"> 
<hibernate-mapping> 
  <class name="com.hibernate.collectionmapping" table="t_collection_mapping"> 
    <id name="id"> 
      <generator class="native"/> 
    </id> 
    <property name="name"/> 
     
    <set name="setvalues" table="t_set_values"> 
      <key column="set_id"></key> 
      <element type="string" column="set_value"></element> 
    </set> 
    <list name="listvalues" table="t_list_values"> 
      <key column="list_id"/> 
      <list-index column="list_index"/> 
      <element type="string" column="list_value"/> 
    </list> 
    <map name="mapvalues" table="t_map_values"> 
      <key column="map_id"/> 
      <map-key type="string" column="map_key"/> 
      <element type="string" column="map_value"/> 
    </map> 
    <array name="arrayvalues" table="t_array_value"> 
      <key column="array_id"/>      
      <index column="array_index" type="integer"></index> 
      <element type="string" column="array_value"/> 
    </array> 
  </class> 
</hibernate-mapping> 

需要注意的是list标签和array标签,这两种集合内的对象是有顺序的,所以在添加映射标签时需要使用list-index或者index标签来标明对象的顺序,而且在添加子标签时一定要按照顺序添加,也就是说先添加<key>标签,后添加<list-index>标签,最后添加<element>标签,否则的话会出现如下错误:
the content of element type "list" must match "(meta*,subselect?,cache?,synchronize*,comment?,key,(index|list-index),(element|one-to-many|many-to-many|composite-element|many-to-any),loader?,sql-insert?,sql-update?,sql-delete?,sql-delete-all?,filter*)".

5.关系模型
将配置好的对象模型转化为相应的关系模型,生成的sql语句如下:

alter table t_array_value drop foreign key fk2e0dd0c067676b68 
alter table t_list_values drop foreign key fke01ec98bf4fcb03 
alter table t_map_values drop foreign key fkd169ba107402b585 
alter table t_set_values drop foreign key fk7bb8d04a7e79f8bf 
drop table if exists t_array_value 
drop table if exists t_collection_mapping 
drop table if exists t_list_values 
drop table if exists t_map_values 
drop table if exists t_set_values 
create table t_array_value (array_id integer not null, array_value varchar(255), array_index integer not null, primary key (array_id, array_index)) 
create table t_collection_mapping (id integer not null auto_increment, name varchar(255), primary key (id)) 
create table t_list_values (list_id integer not null, list_value varchar(255), list_index integer not null, primary key (list_id, list_index)) 
create table t_map_values (map_id integer not null, map_value varchar(255), map_key varchar(255) not null, primary key (map_id, map_key)) 
create table t_set_values (set_id integer not null, set_value varchar(255)) 
alter table t_array_value add index fk2e0dd0c067676b68 (array_id), add constraint fk2e0dd0c067676b68 foreign key (array_id) references t_collection_mapping (id) 
alter table t_list_values add index fke01ec98bf4fcb03 (list_id), add constraint fke01ec98bf4fcb03 foreign key (list_id) references t_collection_mapping (id) 
alter table t_map_values add index fkd169ba107402b585 (map_id), add constraint fkd169ba107402b585 foreign key (map_id) references t_collection_mapping (id) 
alter table t_set_values add index fk7bb8d04a7e79f8bf (set_id), add constraint fk7bb8d04a7e79f8bf foreign key (set_id) references t_collection_mapping (id) 

生成的对应的数据库视图如下:

Java的Hibernate框架中集合类数据结构的映射编写教程

Java的Hibernate框架中集合类数据结构的映射编写教程

二、数据操作
1.数据写入
写入数据操作,将数据写入时需要注意创建数据对象,其中的list、set、map需要创建数据对象,将数据对象写入到数据库中,因为它们三者都是对象接口,所以需要创建一个对象,将对象写入到数据库中,具体代码如下:

@suppresswarnings({ "unchecked", "rawtypes" }) 
public void testsave(){ 
   
  session session=null; 
  try{ 
    session=hibernateutils.getsession(); 
    session.begintransaction(); 
     
    collectionmapping cm=new collectionmapping(); 
    cm.setname("zhangsan"); 
     
    set set=new hashset(); 
    set.add("a"); 
    set.add("b"); 
    cm.setsetvalues(set); 
     
    list list=new arraylist(); 
    list.add("list1"); 
    list.add("list2"); 
    cm.setlistvalues(list); 
     
    string[] str=new string[]{"array1","array2"}; 
    cm.setarrayvalues(str); 
     
    map map=new hashmap(); 
    map.put("k1","v1"); 
    map.put("k2", "v2"); 
    cm.setmapvalues(map); 
     
    session.save(cm); 
    session.gettransaction().commit(); 
  }catch(exception e){ 
    e.printstacktrace(); 
    session.gettransaction().rollback(); 
  }finally{ 
    hibernateutils.closesession(session); 
  } 
} 

生成的sql语句如下:

hibernate: insert into t_collection_mapping (name) values (?) 
hibernate: insert into t_set_values (set_id, set_value) values (?, ?) 
hibernate: insert into t_set_values (set_id, set_value) values (?, ?) 
hibernate: insert into t_list_values (list_id, list_index, list_value) values (?, ?, ?) 
hibernate: insert into t_list_values (list_id, list_index, list_value) values (?, ?, ?) 
hibernate: insert into t_map_values (map_id, map_key, map_value) values (?, ?, ?) 
hibernate: insert into t_map_values (map_id, map_key, map_value) values (?, ?, ?) 
hibernate: insert into t_array_value (array_id, array_index, array_value) values (?, ?, ?) 
hibernate: insert into t_array_value (array_id, array_index, array_value) values (?, ?, ?) 

2.加载数据
加载数据的方法很简单,它会将表中的数据按照集合加载到对象中,然后只需要获取相应的对象集合即可。

public void testload(){ 
  session session=null; 
  try{ 
    session=hibernateutils.getsession(); 
    session.begintransaction(); 
     
    collectionmapping cm=(collectionmapping)session.load(collectionmapping.class, 1); 
     
    system.out.println("cm.name= "+cm.getname()); 
    system.out.println("cm.list= "+cm.getlistvalues()); 
    system.out.println("cm.map= "+cm.getmapvalues()); 
    system.out.println("cm.array= "+cm.getarrayvalues()); 
    system.out.println("cm.set= "+cm.getsetvalues()); 
     
    session.gettransaction().commit(); 
  }catch(exception e){ 
    e.printstacktrace(); 
    session.gettransaction().rollback(); 
  }finally{ 
    hibernateutils.closesession(session); 
  } 
} 

生成的结果:

hibernate: select collection0_.id as id0_0_, collection0_.name as name0_0_ from t_collection_mapping collection0_ where collection0_.id=? 
hibernate: select arrayvalue0_.array_id as array1_0_, arrayvalue0_.array_value as array2_0_, arrayvalue0_.array_index as array3_0_ from t_array_value arrayvalue0_ where arrayvalue0_.array_id=? 
cm.name= zhangsan 
hibernate: select listvalues0_.list_id as list1_0_, listvalues0_.list_value as list2_0_, listvalues0_.list_index as list3_0_ from t_list_values listvalues0_ where listvalues0_.list_id=? 
cm.list= [list1, list2] 
hibernate: select mapvalues0_.map_id as map1_0_, mapvalues0_.map_value as map2_0_, mapvalues0_.map_key as map3_0_ from t_map_values mapvalues0_ where mapvalues0_.map_id=? 
cm.map= {k1=v1, k2=v2} 
cm.array= [ljava.lang.string;@758d8478 
hibernate: select setvalues0_.set_id as set1_0_, setvalues0_.set_value as set2_0_ from t_set_values setvalues0_ where setvalues0_.set_id=? 
cm.set= [b, a] 

三、总结
hibernate可以持久化以下java集合的实例, 包括java.util.map, java.util.set, java.util.sortedmap, java.util.sortedset, java.util.list, 和任何持久实体或值的数组(使用set集合类型是最好的选择)。类型为java.util.collection或者java.util.list的属性还可以使用"bag"语义来持久。用于持久化的集合,除了集合接口外,不能保留任何实现这些接口的类所附加的语义(例如:linkedhashset带来的迭代顺序)。所有的持久化集合,实际上都各自按照 hashmap, hashset, treemap, treeset 和 arraylist 的语义直接工作。更深入地说,对于一个包含集合的属性来说,必须把java类型定义为接口 (也就是map, set 或者list等),而绝不能是hashmap, treeset 或者 arraylist。存在这个限制的原因是,在你不知道的时候,hibernate暗中把你的map, set 和 list 的实例替换成了它自己的关于map, set 或者 list 的实现。(所以在你的程序中,谨慎使用==操作符。)(说明: 为了提高性能等方面的原因,在hibernate中实现了几乎所有的java集合的接口(为了实现懒加载的一些特性) 。)所有的有序集合类(maps, lists, arrays)都拥有一个由<key> 和 <index> 组成的主键。 这种情况下集合类的更新是非常高效的——主键已经被有效的索引,因此当hibernate试图更新或删除一行时,可以迅速找到该行数据。集合(sets)的主键由<key> 和其他元素字段构成。 对于有些元素类型来说,这很低效,特别是组合元素或者大文本、大二进制字段; 数据库可能无法有效的对复杂的主键进行索引。 另一方面,对于一对多、多对多关联,特别是合成的标识符来说,集合也可以达到同样的高效性能。( 附注:如果你希望schemaexport 为你的<set> 创建主键, 你必须把所有的字段都声明为not-null="true" 。)<idbag> 映射定义了代理键,因此它总是可以很高效的被更新。事实上, <idbag> 拥有着最好的性能表现。bag是最差的。因为bag允许重复的元素值 ,也没有索引字段,因此不可能定义主键。 hibernate无法判断出重复的行。当这种集合被更改时,hibernate将会先完整地移除 (通过一个(in a single delete ))整个集合,然后再重新创建整个集合。 因此bag是非常低效的。