- 浏览: 111895 次
- 性别:
- 来自: 武汉
最新评论
-
qbjshmilykm:
hao wen , xue xi
在日本的软件工程师之路 -
nevernam:
去到日本享福赚大钱不吃什么苦
还有这种思维的人估计就太幼稚了 ...
在日本的软件工程师之路 -
tyq168:
这些方法都是啥时候调用呢?我即使登录了怎么还显示在线人数为0呢 ...
HttpSessionListener -
唯快不破:
好!谢谢!
写给准备面试的兄弟姐妹们 -
lzt20032012:
...
java类之Locale,ResourceBundle
构造这样一个例子,在测试过程中来说明一些Hibernate的高级配置及其相关机制:
有三个类:Category.java,Prodcuct.java,ConfigurationTest.java,其中第三个类是用来测试的。
Category.java代码:
Product.java代码:
Category代表产品目录,而Product代表产品,显然Category与Product是一对多的关系。Hibernate在映射一对多关系时,有两种方式,一种是单向一对多,一种是双向关系。两者相比,双向一对多的好处体现在两方面:首先,也是很明显的一点,由于是双向关联,我们在实际业务逻辑时将更方便,例如我们可以检索一个Category下的所有Product,同时还可以检索出Product属于哪个。其次,双向关系相对单向关系而言,在数据库的访问方面更有优势。这一点留在后面讲inverse时讲
。双向关联比单向关联唯一的”劣势“,就在于双向关联需要比单向关联多写一个映射文件,这不问题。使用双向关联实现这两个类同数据库的映射:
现在把这个例子所牵涉到的知识一一展开:
一.inverse
该词的译意是“反转”,反转什么——反转控制端,这项配置决定了由关联双方中的哪一方来维持关联关系(在数据库中表现为外键约束)。上述配置中,在Category.hbm.xml中将inverse设置为true,意思是说“我需要反转(控制端)”,反转的结果是由对方即Product来维持关联关系。用单向关联更容易说明”维持关联关系“是什么意思:考虑用单向关系来实现这个映射关系的情况,即由Category关联到Product,考虑下面的代码:
会执行三条SQL语句:两条插入语句,分别插入c和p,然后还有一条update语句建立起c和p的关联(更新p的外键)。上面,我们说由Category端控制关联,因此p.setCategory(c)这样一句话是没用的,它并不会导致在插入p的时候就设置p的外键以建立起两者的关联关系,从而节省一条update语句。同时我们还会看到,如果在数据库模式中将p的外键设置成非空,这些代码将不能执行,因为在插入p时,由于c和p的关联关系还未建立起来,因此p的外键为空。回到双向关联上来,为了更清楚地明白inverse在双向关联中到底起什么作用,我们分别将其值设为true和false,看看打印出的的SQL有何区别:
为什么inverse=true时会比inverse=false时少执行一条SQL语句?这是由控制端的不同造成的。前者说"我要反转控制,由Product来控制关联",因此在将p对象insert时,p已经设置了其category字段,从而建立了关联关系,而后者说"我不反转控制,由我自己来控制关联",因此在将p对象insert后,c为了维持两者的关联,还要去执行一次update,以更新p的外键,从而建立起两者的关联关系。
结论:对于一对多双向关系,始终在“一”那一方将其inverse设置成true,这样会提高性能。
二.cascade
级联。当关联的"一"方进行某种动作(更新,删除)时,"多"方即使没有显式地进行编码,它也会自动进行同样的动作。cascade的可选值有:
all : 所有情况下均进行关联操作。即是save-update + delete
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。
all-delete-orphan:A:级联save-update B级联delete C:删除所有孤儿项(orphan孤儿)。先看看父子关系,例如在Customer和Order的模型中,这两者便是父子关系,当一个Customer的生命周期决定Order的生命周期,如果一个Customer不在了,其相关的Order继续存在是毫无业务意义的。删除所有孤儿项的意思即是,删除所有与父对象失去关联关系的子对象。
三.lazy
是否延迟加载。一般来说,应该延迟加载,即将lazy设为true。延迟加载的相关点很多,这在另外的学习笔记中总结。
四.unsaved-value
以上是"一"方的重要配置,再看看"多"方的一个重要配置:unsaved-value,就像上面Product.hbm.xml中的设置那样,这一项在id的配置中设置。这一设置是与级联一起工作的。关于这一点,robbin讲的很清楚:
当你显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value 的。某些情况下(父子表关联保存),当你在程序中并没有显式的使用save或者update一个持久对象,那么Hibernate需要判断被操作的对象究竟是一个已经持久化过的持久对象,是一个尚未被持久化过的内存临时对象。例如:
在上例中,程序并没有显式的session.save(child); 那么Hibernate需要知道child究竟是一个临时对象,还是已经在数据库中有的持久对象。如果child是一个新创建的临时对象(本例中就是这种情况),那么Hibernate应该自动产生session.save(child)这样的操作,如果child是已经在数据库中有的持久对象,那么 Hibernate应该自动产生session.update(child)这样的操作。因此我们需要暗示一下Hibernate,究竟 child对象应该对它自动save还是update。在上例中,显然我们应该暗示Hibernate对child自动save,而不是自动 update。那么Hibernate如何判断究竟对child是save还是update呢?它会取一下child的主键属性 child.getId() ,这里假设id是 java.lang.Integer类型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate认为 child是新的内存临时对象,发送save,如果不相等,那么Hibernate认为child是已经持久过的对象,发送update。unsaved-value="null" (默认情况,适用于大多数对象类型主键 Integer/Long/String/...)
当Hibernate取一下child的Id,取出来的是null(在上例中肯定取出来的是null),和unsaved-value设定值相等,发送save(child)
当Hibernate取一下child的id,取出来的不是null,那么和unsaved-value设定值不相等,发送update(child)
unsaved-value的可选配置有:
none,any,null
unsaved-value="none"和unsaved-value="any"主要用在主键属性不是通过Hibernate生成,而是程序自己setId()的时候。unsaved-value="none"和unsaved-value="any"究竟有什么含义了。如果你非要用assigned不可,那么继续解释一下:
unsaved-value="none" 的时候,由于不论主键属性为任何值,都不可能为none,因此Hibernate总是对child对象发送update(child)
unsaved-value="any" 的时候,由于不论主键属性为任何值,都肯定为any,因此Hibernate总是对child对象发送save(child)
大多数情况下,可以避免使用assigned,只有当你使用复合主键的时候不得不手工setId(),这时候需要你自己考虑究竟怎么设置unsaved-value了,根据你自己的需要来定。
关于为什么不要使主键带有义务意义,robbin的解释很清楚:还是以上面的例子打比方,如果我们将Category的某一个性质(比如产品序号或者名称)作为主键,如果后来由于业务需要,我们把这个性质改了,那将不可僻免地要去修改与这个对象相关联的所有数据的外键,而如果我们只要代理主键,这个问题就可完全僻免。
有三个类:Category.java,Prodcuct.java,ConfigurationTest.java,其中第三个类是用来测试的。
Category.java代码:
- package unsaved_value;
- import ......
- public class Category {
- private Integer id;
- private String name;
- private String description;
- private Set <product> products; </product>
- public Category(){
- id=null;
- name=null;
- description=null;
- products=new HashSet <product>(); </product>
- }
- public void addProduct(Product p){
- products.add(p);
- }
- //**********setter and getter
- ........
- }
Product.java代码:
- package unsaved_value;
- public class Product {
- private Integer id;
- private String name;
- private Category category;
- private String description;
- public Product(){
- }
- //*******getter and setter
- .........
- }
ConfigurationTest.java
- public void testSave()throws Exception{
- Category category=new Category();
- category.setName("java编程书籍2");
- category.setDescription("编程经典书籍2");
- Product pro=new Product();
- pro.setName("java编程思想2");
- pro.setDescription("第四版中文版2");
- pro.setCategory(category);
- category.addProduct(pro);
- Transaction tx=session.beginTransaction();
- assert (session!=null):("session is null");
- session.save(category);
- tx.commit();
- }
Category代表产品目录,而Product代表产品,显然Category与Product是一对多的关系。Hibernate在映射一对多关系时,有两种方式,一种是单向一对多,一种是双向关系。两者相比,双向一对多的好处体现在两方面:首先,也是很明显的一点,由于是双向关联,我们在实际业务逻辑时将更方便,例如我们可以检索一个Category下的所有Product,同时还可以检索出Product属于哪个。其次,双向关系相对单向关系而言,在数据库的访问方面更有优势。这一点留在后面讲inverse时讲
。双向关联比单向关联唯一的”劣势“,就在于双向关联需要比单向关联多写一个映射文件,这不问题。使用双向关联实现这两个类同数据库的映射:
- Category.hbm.xml:
- version="1.0" encoding="UTF-8"?>
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="unsaved_value">
- <class name="Category" table="category">
- <id name="id" column="id">
- <generator class="native"><!---->generator>
- <!---->id>
- <property name="name" column="name"/>
- <property name="description" column="description"/>
- <set name="products" table="product" lazy="true" inverse="true" cascade="all">
- <key column="category"/>
- <one-to-many class="Product"/>
- <!---->set>
- <!---->class>
- <!---->hibernate-mapping>
Product.hbm.xml:
- version="1.0" encoding="UTF-8"?>
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="unsaved_value">
- <class name="Product" table="product">
- <id name="id" column="id" unsaved-value="null">
- <generator class="native">generator>
- id>
- <property name="name" column="name"/>
- <property name="description" column="description"/>
- <many-to-one name="category"
- column="category"
- class="Category"
- />
- class>
- hibernate-mapping>
现在把这个例子所牵涉到的知识一一展开:
一.inverse
该词的译意是“反转”,反转什么——反转控制端,这项配置决定了由关联双方中的哪一方来维持关联关系(在数据库中表现为外键约束)。上述配置中,在Category.hbm.xml中将inverse设置为true,意思是说“我需要反转(控制端)”,反转的结果是由对方即Product来维持关联关系。用单向关联更容易说明”维持关联关系“是什么意思:考虑用单向关系来实现这个映射关系的情况,即由Category关联到Product,考虑下面的代码:
- Product p=new Product();
- ..setXXX
- Category c=new Category();
- ..设置Category的属性
- c.addProduct(p);//建立起了c和p的关联关系
- session.save(c);
会执行三条SQL语句:两条插入语句,分别插入c和p,然后还有一条update语句建立起c和p的关联(更新p的外键)。上面,我们说由Category端控制关联,因此p.setCategory(c)这样一句话是没用的,它并不会导致在插入p的时候就设置p的外键以建立起两者的关联关系,从而节省一条update语句。同时我们还会看到,如果在数据库模式中将p的外键设置成非空,这些代码将不能执行,因为在插入p时,由于c和p的关联关系还未建立起来,因此p的外键为空。回到双向关联上来,为了更清楚地明白inverse在双向关联中到底起什么作用,我们分别将其值设为true和false,看看打印出的的SQL有何区别:
inverse=true时的打印结果:
- Hibernate: insert into category (name, description) values (?, ?)
- Hibernate: insert into product (name, description, category) values (?, ?, ?)
inverse=false时的打印结果:
- Hibernate: insert into category (name, description) values (?, ?)
- Hibernate: insert into product (name, description, category) values (?, ?, ?)
- Hibernate: update product set category=? where id=?
结论:对于一对多双向关系,始终在“一”那一方将其inverse设置成true,这样会提高性能。
二.cascade
级联。当关联的"一"方进行某种动作(更新,删除)时,"多"方即使没有显式地进行编码,它也会自动进行同样的动作。cascade的可选值有:
all : 所有情况下均进行关联操作。即是save-update + delete
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。
all-delete-orphan:A:级联save-update B级联delete C:删除所有孤儿项(orphan孤儿)。先看看父子关系,例如在Customer和Order的模型中,这两者便是父子关系,当一个Customer的生命周期决定Order的生命周期,如果一个Customer不在了,其相关的Order继续存在是毫无业务意义的。删除所有孤儿项的意思即是,删除所有与父对象失去关联关系的子对象。
三.lazy
是否延迟加载。一般来说,应该延迟加载,即将lazy设为true。延迟加载的相关点很多,这在另外的学习笔记中总结。
四.unsaved-value
以上是"一"方的重要配置,再看看"多"方的一个重要配置:unsaved-value,就像上面Product.hbm.xml中的设置那样,这一项在id的配置中设置。这一设置是与级联一起工作的。关于这一点,robbin讲的很清楚:
当你显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value 的。某些情况下(父子表关联保存),当你在程序中并没有显式的使用save或者update一个持久对象,那么Hibernate需要判断被操作的对象究竟是一个已经持久化过的持久对象,是一个尚未被持久化过的内存临时对象。例如:
Session session = ...;
- Transaction tx = ...;
- Parent parent = (Parent) session.load(Parent.class, id);
- Child child = new Child();
- child.setParent(parent);
- child.setName("sun");
- parent.addChild(child);
- s.update(parent);
- s.flush();
- tx.commit();
- s.close();
当Hibernate取一下child的Id,取出来的是null(在上例中肯定取出来的是null),和unsaved-value设定值相等,发送save(child)
当Hibernate取一下child的id,取出来的不是null,那么和unsaved-value设定值不相等,发送update(child)
unsaved-value的可选配置有:
none,any,null
unsaved-value="none"和unsaved-value="any"主要用在主键属性不是通过Hibernate生成,而是程序自己setId()的时候。unsaved-value="none"和unsaved-value="any"究竟有什么含义了。如果你非要用assigned不可,那么继续解释一下:
unsaved-value="none" 的时候,由于不论主键属性为任何值,都不可能为none,因此Hibernate总是对child对象发送update(child)
unsaved-value="any" 的时候,由于不论主键属性为任何值,都肯定为any,因此Hibernate总是对child对象发送save(child)
大多数情况下,可以避免使用assigned,只有当你使用复合主键的时候不得不手工setId(),这时候需要你自己考虑究竟怎么设置unsaved-value了,根据你自己的需要来定。
关于为什么不要使主键带有义务意义,robbin的解释很清楚:还是以上面的例子打比方,如果我们将Category的某一个性质(比如产品序号或者名称)作为主键,如果后来由于业务需要,我们把这个性质改了,那将不可僻免地要去修改与这个对象相关联的所有数据的外键,而如果我们只要代理主键,这个问题就可完全僻免。
发表评论
-
java.lang.NoClassDefFoundError: org/apache/log4j/Category
2007-11-08 10:59 4255如果jre\lib\ext下面的包和工程的lib重复 ... -
Spring整合Hibernate
2007-07-04 18:04 2561Spring整合Hibernate时,主要做了两件事:提供事务 ... -
映射文件的自动生成
2007-06-30 22:05 1495选择Myeclipse-xdoclet---->add ... -
PreparedStatement
2007-05-31 18:49 16951.先说数据库是如何处理各种数据库操作语句的: 当数据库接 ... -
DAO范型
2007-05-30 22:34 1331java 代码 public interfac ... -
load()和get()
2007-05-30 20:40 12881.load()前提是确信被load的对象在数据库中存在,否则 ... -
save(),update(),saveOrUpdate()
2007-05-30 20:27 28681.save()导致的最终结果是执行insert语句,先看下面 ... -
自然主键和复合主键
2007-05-30 18:24 18201. 自然主键 代理主键是没有业务意义的主键,这是 ... -
URI资源路径
2007-05-06 11:50 29621.<html:img src="" ... -
Requested resource is not available
2007-05-06 09:51 5122原先应用运行的蛮好,但是把过滤器的filter-c ... -
级联策略
2007-05-02 17:34 2387Session的文档中将一个对象的状态分为三种: tr ... -
源码之Transaction
2007-05-02 13:27 11161.JDBC实现的事务: import jav ... -
Hibernate配置问题
2007-04-27 22:41 11951.必须为每个持久化类设置属性id,并在其配置文件中将id映射 ... -
struts调试错误
2007-04-20 20:25 14911.exception: cannot find actio ... -
一次收获甚多的调试经历
2007-04-18 11:00 1225//LoginAction.java package nets ...
相关推荐
### Linux 高级配置和管理 #### 一、编译系统——一切软件的运行基础 在深入了解Linux系统及其管理之前,我们首先需要明确一个概念:编译系统的重要性。无论是操作系统本身还是运行在其上的任何程序,都需要经过...
《Windows CE嵌入式高级编程及其实例详解》是一本深度探讨Windows CE操作系统在嵌入式领域的高级开发技术的专业书籍。Windows CE是微软为小型设备和嵌入式系统设计的操作系统,它提供了丰富的功能和高度的可定制性,...
《EVC高级编程及其应用开发》系列书籍显然是一套深入探讨EVC编程技术的专业教程,旨在帮助开发者提升在嵌入式系统中的编程技能和应用开发能力。本部分主要聚焦于该系列的第二卷,涵盖了从第四章到第九章的内容。 一...
### Tivoli OMNbus高级配置详解 #### IBM Tivoli Netcool/OMNIbus 7.3 高级配置技术概述 IBM Tivoli Netcool/OMNIbus 是一个全面且灵活的事件管理解决方案,它能有效地收集、关联、过滤网络及系统中的各类事件信息...
《Windows CE嵌入式高级编程及其实例详解》是一本深入探讨Windows CE操作系统在嵌入式领域的高级开发技术的书籍。这本书涵盖了从基础概念到实际应用的广泛内容,旨在帮助开发者提升在Windows CE平台上的编程技能。...
《EVC高级编程及其应用开发》是一本针对嵌入式领域中使用EVC(Embedded Visual C++)进行软件开发的专业书籍。EVC是微软推出的一种用于Windows CE平台的开发工具,它结合了Visual C++的强大功能,使得开发者能够在...
《Windows CE嵌入式高级编程及其实例详解》是一份深度探讨Windows CE嵌入式系统开发的资源集合,其中包含了多个文档,详细讲解了Windows CE平台的高级编程技术和实际应用案例。以下是对这些文档可能涵盖内容的详尽...
《深入理解Core Java及其配置》 Core Java是Java编程的基础,涵盖了Java语言的核心特性与API,对于任何Java开发者来说,都是必备的知识体系。本篇将深入探讨Core Java的关键概念,并结合配置方面,帮助读者全面掌握...
**EVC高级编程及其应用开发源代码** EVC(Embedded Visual C++)是微软公司推出的一款专门用于开发Windows CE操作系统的嵌入式应用程序的集成开发环境。它基于Visual Studio,为开发者提供了强大的C++编译器和调试...
在深入探讨EVC高级编程时,书籍会涉及内存管理、多线程编程、同步机制、设备驱动开发、网络编程等多个关键领域。这些知识点对于开发高效、稳定且适应性强的嵌入式应用至关重要。此外,书中可能还会介绍如何利用WinCe...
文章首先概述了SMTP的基本工作流程及其身份验证机制,随后介绍了如何检查并设置Domino服务器来避免成为开放转发服务器,最终达到抵御垃圾邮件的目的。 #### SMTP流程与身份验证 - **SMTP流程**:SMTP(简单邮件...
《EVC高级编程及其应用开发》是一套专为Windows CE平台上的Embedded Visual C++(EVC)开发者设计的深入学习教程。这套书籍分为多卷,其中提到的是第三卷(10-13章)。EVC作为微软提供的一个专门用于开发嵌入式系统...
最后,STP的配置通常涉及到启用STP并选择合适的STP模式,比如快速生成树协议(RSTP)或更高级的多实例STP(MSTP)。配置STP主要是为了在网络设备之间建立一个无环拓扑结构,以确保在任何情况下数据都能通过唯一的...
在"EVC高级编程及其应用开发第5.6.7.8.9.10.11章"这个主题中,我们可以深入探讨多个关键的Windows CE(WINCE)平台的编程概念和技术。这些章节覆盖了从基础到高级的多个方面,包括线程管理、文件与注册表操作...
深入讨论高级功能,如启用了HA(高可用性)、DRS(分布式资源调度程序)的步骤和配置vMotion的基本原理,此外,详述监控和审计机制及性能管理的多种手段。 适合人群:系统管理员、IT架构师以及其他负责虚拟化环境...
从给定的文件信息来看,虽然大部分内容与Unix高级管理和配置的主题不直接相关,但我们可以从中提炼出几个关键的知识点,这些知识点对于理解和深入研究Unix系统管理与配置至关重要。 ### Unix高级管理和配置的关键...
本手册针对DPtech LSW6600系列以太网交换机的配置进行详尽介绍,内容涵盖了从基本维护命令行操作到高级网络功能配置的方方面面。DPtech LSW6600系列以太网交换机是一种广泛应用在企业级网络环境的设备,它具备了丰富...
### 利用MPLAB_XC16_C编译器进行16位标准外设和高级外设配置 #### 重要知识点概览 本课程旨在深入讲解如何利用MPLAB_XC16_C编译器对Microchip的16位微控制器(MCU)和数字信号控制器(DSC)进行标准外设和高级外设的...