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

hibernate学习之第十篇

阅读更多

级联和关系维护
Cascade 用来说明当对主对象进行某种操作时,是否对其关联的从对象也作类似的操作,常用的cascade:none,all,save-update,delete,lock,refresh,evict,replicate,persist,merge,delete-orphan(one-to-many).一般对many-to-many,many-to-many不设置级联,在<one-to-one>和<one-to-one>中设置级联。

inverse表示“是否放弃维护关联关系 ”(在java里两个对象产生关联时,对数据库表的影响),在one-to-many和many-to-many的集合定义中使用,inverse=“true”表示该对象不维护关联关系;该属性的值一般在使用有序集合时设置成false(注意hibernate的缺省值是false )。
one-to-many维护关联关系就是更新外键。many-to-many维护关联关系就是在中间表增减记录。
注:配置成one-to-one的对象不维护关联关系。

接着上面的部门和员工的例子:
department的映射配置文件为:

<?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"/>
               
                <map name="emps">
                        <key column="depart_id" />
                        <map-key type="string" column="name"/>
                        <one-to-many class="Employee" />
                </map>
        </class>
</hibernate-mapping>
 

程序:

static void add(){
     Department depart = new Department();
        depart.setName("depart");

        Employee e1 = new Employee();
        e1.setName("e1");
        Employee e2 = new Employee();
        e2.setName("e2");

        Map<String, Employee> emps = new HashMap<String, Employee>();
        emps.put(e1.getName(), e1);
        emps.put(e2.getName(), e2);

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

 

执行以上代码,程序出现异常:严重: Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: hibernate.collections.Employee

在代码中,department知道了employee.s1和s2未持久化,使得保存department时出现异常。 把配置文件做一下修改,
                <map name="emps" cascade="save-update" >
                        <key column="depart_id" />
                        <map-key type="string" column="name"/>
                        <one-to-many class="Employee" />
                </map>


再运行以上代码,就可以正确的保存s1和s2了,因为对他们进行了级联操作,保存department时,也save了employee。

级联操作,可以把上面的选项以逗号分隔开,逐一添加即可。如:
  <map name="emps" cascade="save-update,delete,refresh" ></map>

但级联操作也要慎用,要根据自己具体的业务需求来进行相关配置。

还有:
在修改department.hbm.xml配置文件:

        <map name="emps">
                        <key column="depart_id" />
                        <map-key type="string" column="name"/>
                        <one-to-many class="Employee" />
                </map>
 

执行以下代码:

 static void add() {
        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);

        Map<String, Employee> emps = new HashMap<String, Employee>();
        emps.put(e1.getName(), e1);
        emps.put(e2.getName(), 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=?, name=? where id=?
Hibernate: update Employee set depart_id=?, name=? where id=?
 


上面的三条插入语句很容易理解。下面的四条更新语句分别对应:
 e1.setDepart(depart);
 e2.setDepart(depart);
 depart.setEmps(emps);
可以验证,如果把 e1.setDepart(depart);   e2.setDepart(depart);这两句注释掉,产生的更新语句只有两条:

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 depart_id=?, name=? where id=?
Hibernate: update Employee set depart_id=?, name=? where id=?
 



由此可见,hibernate根据程序代码的执行,采取相应的操作。其实更新语句只需做一次就够了 。对于数据库而言,在程序中,告诉部门有哪些员工,或者告诉员工,你属于那个部门。对于前者,部门需要维护关系。对于后者,员工需要维护关系。他们最终都可以在数据库表中表达出部门和员工的关系。在程序中对两者都手动设定了双方的关系,这样也可以,但显得有些冗余(做了两次更新)。因此,双方都会对关系进行维护,所以,双方都会向数据库提交设定关系的请求,这就带来了数据的重复设置,正如上面的四条更新语句。

解决问题的方案是:我们可以让其中一方放弃对关系的维护。 我们一般让一方放弃对关系的维护,让多方维护。这也比较好理解,正如现实生活中,老师不一定要记住所有学生,但学生记住老师则相对比较容易。
充:inverse不能在有序的集合中使用 。比如一般不这样配置:
<list name="emps" inverse="true"></list> 原因是,list需要维护添加的顺序,如果放弃了关系的维护,那么顺序就也不回得到hibernate的管理。这无疑是矛盾的。
只要在配置文件中做一下修改即可:
                <map name="emps" inverse="true">
                        <key column="depart_id" />
                        <map-key type="string" column="name"/>
                        <one-to-many class="Employee" />
                </map>
在执行以下代码:

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);

        Map<String, Employee> emps = new HashMap<String, Employee>();
        emps.put(e1.getName(), e1);
        emps.put(e2.getName(), e2);

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


执行的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=?
 


分析
:inverse="true"表示放弃对关系的维护。所以上面的两条更新语句是由Employee的setDepart方法产生的。因为关系有Employee来维护。由于department放弃了关系的维护,即使在代码中做了 depart.setEmps(emps)操作,hibernate也会忽略。通过以上方法,可以有效的减少数据库的操作次数,同时不影响关系的建立。

所谓的关系维护,就是更新外键。

改进:
从以上显示的sql语句,可以看出,在插入employee数据是也是插入了depart_id的,只不过是空值,然后插入department,这时就有了depart_id了,这时就去更新employee表,把depart_id更新。其实可以先保存department,这时一开始就有depart_id了,就不会有更新语句了。
代码如下:

 static void add() {
        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);

        Map<String, Employee> emps = new HashMap<String, Employee>();
        emps.put(e1.getName(), e1);
        emps.put(e2.getName(), e2);

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

 

输出的sql语句为:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
 



心得: 根据程序执行过程中,打印输出的sql语句,只需冷静地分析程序的执行过程,不断地改进调优,可以有效的改善程序的性能。

分享到:
评论

相关推荐

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

    Hibernate4的一些总结

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

    hibernate知识点总结

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

    hibernate经典技术PPT

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

    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

    10. **性能优化**:探讨缓存策略、批处理更新、预加载等提高Hibernate性能的方法。 这个压缩包中的实例可能会涵盖以上所有或部分知识点,通过运行和分析这些实例,开发者可以深入理解Hibernate的工作原理,并提升在...

    hibernate的学习

    【标题】:“Hibernate学习” 【描述】:在深入探讨Hibernate之前,我们首先理解它是一个什么。Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者在Java对象和关系数据库之间建立桥梁,极大地简化了...

    hibernate 模糊查询 分页

    本篇文章将深入探讨如何使用Hibernate实现模糊查询和分页功能,这对于任何需要处理大量数据的应用程序来说都是至关重要的技能。 首先,让我们了解Hibernate的核心概念。Hibernate是一个开源的JPA(Java Persistence...

    Hibernate-api Hibernate文档

    这篇文档旨在提供对Hibernate API的深入理解,帮助开发者更高效地使用Hibernate进行数据库操作。 一、Hibernate概述 Hibernate是Java开发中广泛使用的ORM框架,它提供了一种在Java应用中持久化数据到关系数据库的...

    我的hibernate学习笔记(4)完 ---附完整word格式文件

    在本篇“我的Hibernate学习笔记(4)完”中,我们将深入探讨Hibernate这一流行的Java对象关系映射(ORM)框架,以及如何通过源码和工具进行高效开发。这篇笔记不仅包含理论知识,还提供了实际操作的指导,以帮助读者更...

Global site tag (gtag.js) - Google Analytics