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

一、集合映射

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

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

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)

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

二、数据操作
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是非常低效的。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, hibernate
, 教程
, 映射
Hibernate教程
hibernate 集合映射、hibernate 映射、hibernate 继承映射、hibernate list映射、hibernate注解映射,以便于您获取更多的相关知识。

时间: 2024-10-31 22:25:23

Java的Hibernate框架中集合类数据结构的映射编写教程_java的相关文章

在Java的Hibernate框架中使用SQL语句的简单介绍_java

Hibernate中有HQL查询语法.但我们用得比较熟的还是数SQL语句,那么应该怎么来让Hibernate支持SQL呢?这个不用我们去考虑了,Hibernate团队已经早就做好了.        废话不说,直接来例子啦. select * from t_user usr     上面是一条SQL语句,又是废话,是个人都知道.我们想让Hibernate执行这条语句,怎么办呢?看代码: Query query = session.createSQLQuery("select * from t_us

Java的Hibernate框架中Criteria查询使用的实例讲解_java

我们讲一下Criteria查询,这个对于不是太熟悉SQL语句的我们这些程序员来说是很容易上手的.  废话不多说,看一下例子:  实体类如下: public class User implements Serializable{ private static final long serialVersionUID = 1L; public Long id; private String name; private int age; //省略Get/Set方法 }   映射文件我们就不写了,很简单的

深入解析Java的Hibernate框架中的一对一关联映射_java

作为一个ORM框架,hibernate肯定也需要满足我们实现表与表之间进行关联的需要.hibernate在关联方法的实现很简单.下面我们先来看看一对一的做法:  不多说了,我们直接上代码:  两个实体类,TUser和TPassport: public class TUser implements Serializable{ private static final long serialVersionUID = 1L; private int id; private int age; priva

在Java的Hibernate框架中对数据库数据进行查询操作_java

Hibernate查询语言(HQL)是一种面向对象的查询语言,类似于SQL,但不是对表和列操作,HQL适用于持久对象和它们的属性. HQL查询由Hibernate转换成传统的SQL查询,这在圈上的数据库执行操作. 虽然可以直接使用SQL语句和Hibernate使用原生SQL,但建议使用HQL尽可能避免数据库可移植性的麻烦,并采取Hibernate的SQL生成和缓存策略的优势. 都像SELECT,FROM和WHERE等关键字不区分大小写,但如表名和列名的属性是区分在HQL敏感. FROM 语句使用

Java的Hibernate框架中复合主键映射的创建和使用教程_java

复合主键映射需要在映射配置文件中使用<composite-id>标签,该标签是指将一个类指定为相应的复合主键,它的name属性需要指定类文件中定义的属性值,并在该标签中添加<key-property>子标签. Note:想要使用复合映射必须要将复合主键放到一个类中,也就是讲复合主键属性和其它属性分到两个类中,并将复合主键的类实现接口Serializable,该接口隶属于java.io. 复合主键的映射关系的主键是由多个列复合而成的,对应到数据表中相当的简单,如下图: 1.类文件这里

Java的Struts2框架中拦截器使用的实例教程_java

1.拦截器小介 拦截器的功能类似于web.xml文件中的Filter,能对用户的请求进行拦截,通过拦截用户的请求来实现对页面的控制.拦截器是在Struts-core-2.2.3.jar中进行配置的,原始的拦截器是在struts-default.xml中配置的,里面封存了拦截器的基本使用方法. Struts2拦截器功能类似于Servlet过滤器.在Action执行execute方法前,Struts2会首先执行struts.xml中引用的拦截器,如果有多个拦截器则会按照上下顺序依次执行,在执行完所有

详解Java的Hibernate框架中的Interceptor和Collection_java

Interceptor讲到Interceptor,相信熟悉struts2的童鞋肯定不会陌生了,struts2可以自定义拦截器进行自己想要的一系列相关的工作.而这里我们说的Interceptor也是差不多相似的功能.  废话不说,直接来代码:  下面这个是MyInterceptor类,它实现了Interceptor接口: public String onPrepareStatement(String arg0) { return arg0; } public boolean onSave(Obje

解析Java的Hibernate框架中的持久化类和映射文件_java

持久化类Hibernate的整个概念是采取从Java类属性的值,并将持久到数据库表.一个映射文件Hibernate的帮助确定如何从拉动类的值,并将它们映射与表和相关的域. 其对象或实例将存储在数据库表中的Java类在Hibernate中称为持久化类. Hibernate的效果最好,如果这些类遵循一些简单的规则,也称为普通Java对象(POJO)编程模型.有下列持久化类的主要规则,但是,这些规则并不是必需的. 将所有的持久化Java类需要一个默认的构造函数. 所有类应该包含为了让容易识别对象内Hi

详解Java的Hibernate框架中的注解与缓存_java

注解Hibernate注解是一个没有使用XML文件来定义映射的最新方法.可以在除或替换的XML映射元数据使用注解. Hibernate的注解是强大的方式来提供元数据对象和关系表的映射.所有的元数据被杵到一起的代码POJO java文件这可以帮助用户在开发过程中同时要了解表的结构和POJO. 如果打算让应用程序移植到其他EJB3规范的ORM应用程序,必须使用注解来表示映射信息,但仍然如果想要更大的灵活性,那么应该使用基于XML的映射去. 环境设置Hibernate注释 首先,必须确保使用的是JDK