`
jianchen
  • 浏览: 340597 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

hibernate学习之第九篇

阅读更多

hibernate中的集合类型

引入:
Hibernate可以持久化以下java集合的实例, 包括java.util.Map, java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.List, 和任何持久实体或值的数组。类型为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集合的接口 。)

集合实例在数据库中根据指向对应实体的外键而得到区别。这个外键被称为集合的关键字在Hibernate配置文件中使用<key> 元素来映射这个集合的关键字。

集合可以包含几乎所有的Hibernate类型, 包括所有的基本类型, 自定义类型,实体类型和组件。 集合不能包含其他集合。这些被包含的元素的类型被称为集合元素类型。 集合的元素在Hibernate中被映射为<element>, <composite-element>, <one-to-many>, <many-to-many> 或者 <many-to-any>。
set集合类型用的比较多。
这里举得例子是部门和员工的关系。我们知道部门和员工是一对多的关系。
员工类的源代码如下:

public class Employee {
        private int id;
        private String name;
        private Department depart;

        @Override
        public String toString() {
                return "id=" + this.id + " name=" + this.name;
        }

        public int getId() {
                return id;
        }

        public void setId(int id) {
                this.id = id;
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public Department getDepart() {
                return depart;
        }

        public void setDepart(Department depart) {
                this.depart = depart;
        }
}

 

员工的映射文件:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
        package="hibernate.collections">

    <class name="Employee" >
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" unique="true"/>
        <many-to-one name="depart" column="depart_id"/>
    </class>
</hibernate-mapping>

 

充:hibernate不允许多的这一端放弃对关系的维护。即many-to-one没有inverse=“true”这样的配置。
部门类的源代码如下:

 

public class Department {
        private int id;
        private String name;

        private Set<Employee> emps;

        // private List<Employee> emps;

        // private Map<String, Employee> emps;

        // private Employee[] emps;

        public int getId() {
                return id;
        }

        public void setId(int id) {
                this.id = id;
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public Set<Employee> getEmps() {
                return emps;
        }

        public void setEmps(Set<Employee> emps) {
                this.emps = emps;
        }
}

 

部门类的映射文件department.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.collections">

        <class name="Department">
                <id name="id">
                        <generator class="native" />
                </id>
                <property name="name"/>

                <set name="emps" inverse="true">
                        <key column="depart_id"/>
                        <one-to-many class="Employee" />
                </set>
        </class>

</hibernate-mapping>

 

测试代码:

public class Main {
public static void main(String[] args){
    Department depart = new Department();
    depart.setName("depart");

    Employee e1 = new Employee();
    e1.setName("e1");
    e1.setDepart(depart);

    Employee e2 = new Employee();
    e2.setName("e2");
    e2.setDepart(depart);
  
    Set<Employee> emps = new HashSet<Employee>();
    emps.add(e1);
    emps.add(e2);
    depart.setEmps(emps);

    Session s = HibernateUtil.getSession();
    Transaction tx = s.beginTransaction();
    s.save(e1);
    s.save(e2);
    s.save(depart);
tx.commit();
}
}

 

执行后hibernate执行的sql语句如下:

Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Department (name) values (?)
Hibernate: update Employee set name=?, depart_id=? where id=?
Hibernate: update Employee set name=?, depart_id=? where id=?
Hibernate: update Employee set depart_id=? where id=?
Hibernate: update Employee set depart_id=? where id=?
 



以上用的是set集合类型,它具有这样的特性:无重复和没有顺序。
但有时候我们需要记住元素的顺序,这时就可以采用list来保存元素。同样,在hibernate中有相应的List标签与之对应。他可以在保存的时候记住保存的顺序。例如,部门可以对其员工加入的先后进行记录。读取时,就会按照先后的顺序来获得。
只需在deparment类中把集合类型改用List,同时修改deparment.hbm.xml文件中的set标签:
                         <list name="emps">
                        <key column="depart_id" />
                        <list-index column="order_col" /> //该子元素用于记录保存的顺序,在对象模型中不存在,hibernate会在表中加入一列order_col
                        <one-to-many class="Employee" />
                     </list>
测试代码只需把set改为是有List即可,其他部分不变。

hibernate帮助生成的表结构为:
+---+-------+-----------+-----------+
| id |name |depart_id|order_col|
+----+------+-----------+-----------+
|  1  | e1    |         1    |         0    |
|  2  | e2    |         1    |         1    |
+----+------+-----------+-----------+

有时候,我们虽然在java代码中试用了List集合类型,但我们保存时并不需要记住保存的先后顺序,这时可以用bag标签代替。
<bag name="employees" order-by="id desc">  //不关心顺序,与java代码中的list对应。
    <key column="depart_id"/>
    <one-to-many class="Employee"/>
</bag>
查看表结构为:
+----+------+-----------+
| id | name | depart_id |
+----+------+-----------+
|  1  | e1    |         1    |
|  2  | e2    |         1    |
+----+------+-----------+

map在java中也是一种常用的集合类型。假设员工的名字是不一样的,可以把员工的名字作为键,员工作为map的值。
department类修改为:
public class Department {
        private int id;
        private String name;
        private Map<String, Employee> emps;
}
department.hbm.xml配置文件修改:
                <map name="emps">
                        <key column="depart_id" />
                        <map-key type="string" column="name"/>
                        <one-to-many class="Employee" />
                </map>
测试代码只需把集合类型做相应的改变即可,生成的表结构为:
department表;
+----+--------+
| id | name   |
+----+--------+
|  1 | depart |
+----+--------+
employee表:
+----+------+-----------+
| id | name |depart_id|
+----+------+-----------+
|  1   | e1   |         1    |
|  2   | e2   |         1    |
+----+------+-----------+

介绍了这么多的集合类型,那么我们在实际运用中该如何选呢?
简单使用原则:大部分情况下使用set,需要保证集合中的顺序用list,想用java.util.List又不需要保证顺序用bag。

这些集合类都是Hibernate实现的类和JAVA中的集合类不完全一样,set,list,map分别和java中的set,list,map接口对应,bag映射成java的list;这些集合的使用和java集合中对应的接口基本一致;

注意:在java的实体类中集合只能定义成接口不能定义成具体类,因为集合会在运行时被替换成Hibernate的实现。为了实现懒加载 ,hibernate把java中的集合类都重新给予了实现。你在java中使用的集合类,在保存时hibernate内部进行了替换,使用的是内置的hibernate集合。所以你在程序中用你的集合类进行强制类型转换会出错。

比如下面代码:

static void query(int id) {
        String hql = "from deparment";
        Session s = HibernateUtil.getSession();
        Transaction tx = s.beginTransaction();
        Department depart = (Department)s.get(Department.class, id);
        System.out.println();
        System.out.println(depart.getEmps());
       
    }

 

在主函数中调用该段代码打印输出:{e1=id=1 name=e1, e2=id=2 name=e2}

将以上代码的打印语句改为:System.out.println((HashMap) depart.getEmps());
把它进行强制类型转换,再运行则会报错
出错信息为:Exception in thread "main" java.lang.ClassCastException: org.hibernate.collection.PersistentMap cannot be cast to java.util.HashMap

正如上面所指出的,hibernate对java中的集合类有自己的替代实现,对于hashmap是org.hibernate.collection.PersistentMap,该类继承了java中的Map类。在我们调用session的save语句后,hibernate会将实际的HashMap进行替换,实际上程序使用的是hibernate的自身实现。所以在程序中,再用HashMap进行强制类型转换就会报错。 但是用Map就可以,因为persistentMap是Map的子类。即执行:System.out.println((Map) depart.getEmps());就不会报错。所以在程序中尽量使用java接口,这也符合面向接口编程的道理。

分享到:
评论

相关推荐

    Hibernate中文学习资料

    本篇将主要围绕`Hibernate3中文参考手册`展开,深入探讨Hibernate的基础概念、配置、实体映射、查询语言以及其他关键特性。 1. **Hibernate概述** Hibernate是一个开源的ORM框架,它提供了对Java应用程序的数据库...

    hibernate教程-从入门到精通-第4篇(共四篇)共2

    【hibernate教程-从入门到精通-第4篇(共四篇)共2】这篇教程是关于Java持久层框架Hibernate的学习指南,旨在帮助初学者深入理解并掌握Hibernate的核心概念和技术。Hibernate作为一款强大的对象关系映射(ORM)工具,...

    Hibernate学习笔记(三)

    在本篇“Hibernate学习笔记(三)”中,我们将深入探讨Hibernate这一强大的Java持久化框架。Hibernate是一个对象关系映射(ORM)工具,它允许开发者用面向对象的方式处理数据库操作,极大地简化了Java应用程序与...

    最经典的hibernate教程_从入门到精通_第二篇

    本教程旨在提供一个全面的Hibernate学习路径,让你能够熟练地运用Hibernate进行数据库操作,提升开发效率。通过深入学习,你将掌握如何利用Hibernate进行对象关系映射(ORM),事务管理,查询优化以及与其他技术如...

    Hibernate之第1解之-hibernate_demo_1

    【标题】"Hibernate之第1解之-hibernate_demo_1" 涉及的主要内容是对Hibernate框架的基础理解和应用,这是Java开发中一个重要的持久化工具。这篇博客可能详细介绍了如何搭建Hibernate开发环境,以及进行初步的数据...

    hibernate实践

    这篇文档集合了丰富的Hibernate实践知识,对于初学者来说是一份宝贵的资源。 1. **Hibernate核心概念** Hibernate的核心在于持久化对象,它允许我们将Java类映射到数据库表,对象的属性对应于表的列。实体类是Java...

    hibernate 3,25

    在本篇文章中,我们将深入探讨Hibernate 3.2.5中的核心概念、特性以及它如何简化Java数据库编程。 1. **对象关系映射(ORM)**:Hibernate作为ORM工具,将Java对象与数据库表进行映射,使得开发者可以处理Java对象...

    hibernate测试

    这篇关于“hibernate测试”的文章旨在深入探讨Hibernate的核心概念,以及如何进行有效的测试以确保其在项目中的稳定运行。 1. **Hibernate简介** Hibernate是一个开源的Java库,它为Java应用程序提供了一个框架,...

    Hibernate学习笔记(很详细哦)

    ### Hibernate学习笔记精要 #### 一、HelloWorld与Hibernate入门 **HelloWorld**是学习任何新技术时的经典第一个程序,Hibernate也不例外。通过构建一个简单的Java项目`hibernate_0100_HelloWorld`,我们可以熟悉...

    Hibernate学习笔记

    《Hibernate学习笔记》是一份深度剖析Hibernate框架的教程,旨在为初学者提供全面而深入的指导,帮助他们快速掌握这个强大的Java对象关系映射(ORM)工具。Hibernate作为Java领域中广泛使用的ORM解决方案,它极大地...

    Java Web整合开发王者归来(JSP+Servlet+Struts+Hibernate+Spring)

    第9篇为实战篇,内容为两个典型的应用系统:论坛系统(Spring+Struts+Hibernate)、宠物商店(EJB 3+JPA+Struts 2)。 《Java Web整合开发王者归来(JSP+Servlet+Struts+Hibernate+Spring)》附1张DVD光盘,内容为《Java ...

    hibernate源码release-4.1.4.Final版

    本篇文章将围绕Hibernate 4.1.4.Final版本的源码进行深入探讨,揭示其内部机制,帮助读者提升对Hibernate的理解和应用水平。 一、Hibernate概述 Hibernate是一个开源的ORM框架,它实现了Java持久化模型,将数据库...

    hibernate经典技术PPT

    描述中的"经典heibernate教程,从入门到精通_CSTP-Hibernate02(第二篇,共四篇).ppt"提到了Hibernate教程的第二部分,说明这是一个系列教程,旨在帮助学习者从基础到高级逐步掌握Hibernate。"不错的东西 就是有点看不...

    Hibernate4的一些总结

    【描述】:这篇博客主要涵盖了Hibernate4框架在实际开发中的应用和理解,作者通过个人实践对Hibernate4的核心特性和使用技巧进行了深度解析。 【标签】:“源码”和“工具”这两个标签揭示了本文将涉及到Hibernate4...

    hibernate知识点总结

    这篇文档将对Hibernate的关键概念、配置、实体类、映射文件、会话和事务等方面进行详尽的介绍,以帮助J2EE初学者快速理解和掌握Hibernate。 1. **对象关系映射(ORM)**: ORM是Hibernate的核心,它通过映射文件将...

    hibernate-orm-master.zip

    本篇将从源码的角度,对Hibernate进行深度解析,帮助读者理解其核心机制。 一、Hibernate概览 Hibernate是一个开源的、基于Java的持久化框架,它提供了一种在Java应用和关系数据库之间建立映射的方法,使得开发者...

    hibernate学习笔记

    这篇学习笔记将深入探讨Hibernate的基础和关键特性,包括其核心概念、配置、注解使用以及ORM的核心原理。 1. **Hibernate概述** Hibernate是一个开源的ORM框架,由Gavin King创建,它通过提供一个接口,让开发者...

    Hibernate学习资料

    **Hibernate学习资料** Hibernate是一个强大的Java对象关系映射(ORM)框架,它为开发者提供了在Java应用程序中管理和操作数据库的强大工具。这篇文档将深入探讨Hibernate的核心概念、配置、使用方法以及最佳实践,...

    最经典的hibernate教程_从入门到精通_第四篇

    在“最经典的hibernate教程_从入门到精通_第四篇”中,我们将会深入探讨以下几个关键知识点: 1. **安装与配置**:学习如何在项目中引入Hibernate库,配置hibernate.cfg.xml文件,设置数据库连接参数,以及如何创建...

    Hibernate数据库操作实例.zip

    9. **Spring与Hibernate集成**:理解Spring的DataSource、SessionFactoryBean、HibernateTemplate或JPA的使用,以及事务的声明式管理。 10. **性能优化**:探讨缓存策略、批处理更新、预加载等提高Hibernate性能的...

Global site tag (gtag.js) - Google Analytics