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

深入浅出hibernate摘录2

阅读更多

以下内容摘自深入浅出hibernate

在编写代码的时候,尽量将POJO的getter/setter方法设定为public,如果设定为private,protected,hibernate将无法对属性的存取进行优化,只能转而采用传统的反射机制进行操作(hibernate3中进行了局部改进),这将导致大量的性能开销(特别是在IBM JDK以及1.4之前的sun JDK版本中,反射带来的系统开销相当可观。)

级联关系设置为all。
级联(cascade)在Hibernate映射关系中是个非常重要的概念。它指的是当主控方执行操作时,关联对象(被动方)是否执行同一操作。如对主控对象调用save-update或delete方法时,是否同时对关联对象(被动方)进行save-update或delete。
如果设定为all,则代表无论主控方执行任何操作,都对其关联类进行同样的操作。


Hibernate 3 中,引入了Restrictions类作为Expression的替代(Expression类被设定为半废弃状态),Restrictions的使用方法与Expression一致(Hibernate3中,Expression实际上为Restrictions类的一个子类实现)。

示例查询:
Example类实现了Criteria接口,同样,它也可以用作Criteria的查询条件。Example的作用是:根据已有对象,查找属性与之相符的其他对象。

示例代码:

Criteria criteria = session.createCreateria(TUser.class);

TUser exampleUser = new TUser();
exampleUser.setName("Erica");
criteria.add(Example.create(exampleUser));

List list = criteria.list();

for(int i=0;i<list.size();i++)
{
TUser user = (TUser) list.get(i);
System.out.println("User["+i+"]\t"+user.getName());
}

这里我们新建了一个TUser对象exampleUser,并作为范本,查询所有name属性与之相同的用户记录。

红色代码等价于:criteria.add(Expression.eq("name","Erica"));


DetachedCriteria 可以脱离session实例独立存在,这样,我们就可以将某些通用的criteria查询条件进行抽离,每次使用时再与当前session实例绑定以获得更好的代码重用效果。

HQL子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分。

在hibernate2之前版本中,HQL仅用于数据查询。而在Hibernate3中,HQL具备了更加强大的功能。实体更新与删除就是其中的主要特性之一。

Hibernate中的HQL功能已日趋全面,同时也越来越接近传统的SQL语言。与sql不同的是,sql面向的是二维的结构化数据,而HQL则面向数据对象。在对象数据库尚不成熟的今天,通过面向对象的查询语言对关系型数据库进行访问,既满足了上层结构中面向对象设计的需求,也充分利用了现有技术平台,这也正是Hibernate的优势所在。

SQL Injection 是常见的系统攻击手段,这种攻击方式的目标即针对有SQL字符串拼装造成的漏洞。


参数绑定机制可以使得查询语法与具体参数数值相互独立。

fetch关键字只对inner join和left join有效。对于right join而言,由于作为关联对象容器的T_User对象可能为null,所以也就无法通过fetch关键字强制Hibernate进行集合填充操作。

HQL中,子查询必须出现在where子句中,且必须以一对圆括号包围。

Hibernate支持一下几种数据加载方式:
1,即时加载
当实体加载完成后,立即加载其关联数据。

2,延迟 加载
实体加载时,其关联数据并非即刻获取,而是等关联数据第一次被访问时在进行读取。

3,预先加载
预先加载时,实体及其关联对象同时读取,这与即时加载类似,不过实体及其关联数据是通过一条SQL语句(基于外连接)同时读取。

4,批量加载
对于即时加载和延迟加载,可以采用批量加载方式进行性能上的优化。

批量加载,简而言之,就是通过批量提交多个限定条件,一次完成多个数据的读取。如对于一下形式的sql:
Select from T_User where id=1;
Select from T_User where id=2;

我们可以将其整合成一条sql语句完成同样的功能:
Select from T_User where id=1 or id=2;

这就是所谓的批量加载机制。如果使用了批量加载机制,Hibernate在进行数据查询操作前,会自动在当前session中寻找是否还有其他同类型待加载的数据,如果有,则将其查询条件合并在当前select语句中一并提交,这样,通过一次数据库操作即完成了多个读取任务。

在实体配置的class节点中,我们可以通过

我们可以通过编码将一个Transient状态的对象手动的与库表记录形成关联,使其改造成一个Detached状态的对象,此时,我们手工构造的这个Detached对象与通过Session构造的Detached对象并没有什么区别。
不过,考虑到实际情况可能并非这么简单,Hibernate在判定对象处于Detached状态还是Transient状态时,有着更加复杂的机制。

判定一个对象是否处于Transient状态的条件:
1,首先,对象的id属性(如果此属性存在的话)是否为null
2,对应上面的示例,Hibernatne即根据此条件进行判定。
3,如果指定了id属性的unsaved-value,那么id属性是否等于unsaved-value。
4,如果配备了Version属性,version属性是否为null。
5,如果配备了Version属性,且为version指定了vunsaved-value,version属性值是否等于unsaved-value。
6,如果存在Interceptor,那么Interceptor.isUnsaved方法是否返回true。

VO与PO

有时候,为了方便,我们也将处于Transient和Detached状态的对象统称为值对象,而将处于Persistent状态的对象成为持久对象。
这时站在“实体对象是否被纳入Hibernate实体管理容器”的立场加以区分的,非管理的实体对象统称为VO,而被管理的实体对象成为PO.
在从VO和PO的角度重复一下上面的描述:
VO和PO的主要区别在于:
1,VO是相对独立的实体对象,处于非管理状态
2,PO是由Hibernate纳入其实体管理容器(Entity Map)的对象,它代表了与数据库中某条记录对应的Hibernate实体,PO的变化在事务提交时将反映到实际数据库中。
3,如果一个PO与其对应的session实例分离,那么此时,它又会变成一个VO。
由PO,VO的概念,有引申出一些系统层次设计方面的问题。如在传统的MVC架构中,位于model层的PO,是否允许被传递到其他层面。由于PO的更新最终将被映射到实际数据库中,如果PO在其他层面(如view层)发生了变动,那么可能会对Model层造成意想不到的破坏。
因此,一般而言,应该避免直接将PO传递到系统中的其他层面,一种解决方法是,通过构造一个新的VO,通过属性复制使其具备与PO相同的属性值,并以其为传输煤质(实际上,这个VO被用作Data Transfer Object,即所谓的DTO),将此VO传递给其他层面以实现必须的数据传送。

属性复制可以通过Apache Jakarta Commons Beanutils组件提供的属性批量复制工鞥,避免反复的get/set操作。

Collection在判断两个对象是否相等的时候,会首先调用对象的hashCode方法,如果hashCode相同的话,随即调用其equals方法,如果两次判断均为真,则认为对比的两个对象相等。


事务提交时,Hibernate会对session中的PO进行检测,判断那些发生了变化,并将发生变化的数据更新到数据库中。
这里就存在一个问题,Hibernate如何盘对一个数据对象是否发生了改变,或者说,Hibernate如何进行脏数据识别?
脏数据检查的一般策略大致有下面两种:
1,数据对象监控
数据对象监控的实现方式,大体上是通过拦截器对数据对象的设值方法(setter)进行拦截,拦截器的实现可以借助Dynamic Proxy或者CGLIB实现。一旦数据对象的设置方法被调用(通常也意味着数据对象的内容发生变化),则将其标志为“待更新”状态,之后在数据库操作时将其更新到对应的库表。

2,数据库版本对比
在持久层框架中维持数据对象的最近读取版本,当数据提交时将提交数据与此版本进行比对,如果发生变化则将其同步到数据库相应的库表。

在session中,保存了所有与当前session实例相关联的实体对象的当前实例和原始状态信息(即EntityEntry)。这两者以“key-value”的形式,保存在SessionImpl.entityEntries数据结构中。
SessionImpl.entityEntries是一个Map型的数据结构,其中每个项目(Entry)都包含了当前 与Session关联的一个实体对象实例及其原始信息。以实体对象为key,而以对应EntityEntry为value。session.flushEntities方法的工作,就是遍历entityEntries,并将其中的实体对象与其原始版本进行对比,判断对象状态是否更改。

类 IdentityHashMap
此类利用哈希表实现 Map 接口,比较键(和值)时使用引用相等性代替对象相等性。换句话说,在 IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等(在正常 Map 实现(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2)))。

对于save操作而言,如果对象已经与session向关联(即已经被加入session的实体容器中),则无需进行具体的操作。因为之后的session.flush过程中,Hibernate会对此实体容器中的对象进行遍历,查找出发生变化的实体,生成并执行相应的update语句。

缓存是数据库数据在内存中的临时容器,它包含了库表数据在内存中的临时拷贝,位于数据库与数据访问层之间。ORM在进行数据读取时,会根据其缓存管理策略,首先在缓存中查询,如果在缓存中发现所需数据(缓存命中),则直接以此数据作为查询结果加以利用,从而避免了数据库调用的性能开销。

只有在查询开始之前(也就是Hibernate生成SQL之前)设定加锁,才会真正通过数据库的锁机制进行加锁处理,否则,数据已经通过不包含for update子句的select SQL 加载进来,所谓数据库加锁也就无从谈起。

session在加载实体对象时,将经过哪些过程:
1,首先,我麽欧尼知道,hibernate中维护了两级缓存。第一级缓存由session实例维护,其中保持了session当前所有关联实体的数据,也称为内部缓存。而第二级缓存则存在与sessionFacotory层次,有当前所有由本sessionFacotory构造的session实例共享。
出于性能考虑,避免无谓的数据库访问,session在调用数据库查询功能之前,会现在缓存中进行查询。首先在第一级缓存,通过实体类型和id进行查找,如果第一级缓存查找命中,且数据状态合法,则直接返回。
2,之后,session会在当前“NonExists”记录中进行查找,如果“NonExists”记录中存在同样的查询条件,则返回null。“NonExists”记录了当前session实例在之前所有查询操作中,未能查询到有效数据的查询条件(相当与一个查询黑名单列表)。如此一来,如果session中一个无效的查询条件重复出现,即可迅速做出判断,从而获得最佳的性能表现。
3,对应load方法而言,如果内部缓存中未发现有效数据,则查询第二级缓存,如果第二级缓存命中,则返回。
4,如在缓存中未发现有效数据,则发起数据库查询操作,如经过查询未发现对应记录,则将此次查询的信息在“NonExists“中加以记录,并返回null。
5,根据映射配置和select SQL得到的resultSet,创建对应的数据对象。
6,将其数据对象纳入当前session实体管理容器(一级缓存)。
7,执行Interceptor.onLoad方法(如果有对应的interceptor)。
8,将数据对象纳入二级缓存。
9,如果数据对象实现了LifeCycle接口,则调用数据对象的onLoad方法。
10,返回数据对象。

分享到:
评论

相关推荐

    深入浅出hibernate清晰版

    深入浅出hibernate 清晰版

    深入浅出 Hibernate.pdf

    根据提供的标题“深入浅出 Hibernate.pdf”以及描述“深入浅出 Hibernate.pdf”,我们可以推断这份文档主要讲解了Hibernate框架的相关知识。接下来,我们将基于这些信息展开详细的解释与知识点的梳理。 ### ...

    .深入浅出Hibernate

    深入浅出Hibernate

    深入浅出hibernate

    夏昕的 深入浅出Hibernate&gt;&gt;是一本非常不错的解析Hibernate的书籍

    深入浅出Hibernate(PDF)第二部分

    本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate实战,重点讲述了Hibernate的基础语法、基础配置、O/R映射、数据关联、数据检索、HQL实用技术...

    深入浅出hibernate(PDF)第三部分

    本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate实战,重点讲述了Hibernate的基础语法、基础配置、O/R映射、数据关联、数据检索、HQL实用技术...

    深入浅出Hibernate

    深入浅出Hibernate 作者:夏昕 曹晓刚 7Z压缩:分包一大小18mb、分包二4mb 使用:把两个压缩包一起解压就可以了

    深入浅出Hibernate完整版1

    深入浅出Hibernate完整版,除了资料外,还包括PPT和类型映射关系图

    夏昕.深入浅出Hibernate.rar

    《深入浅出Hibernate》是夏昕撰写的一本关于Hibernate框架的经典教程,对于想要掌握Hibernate技术的开发者来说,这本书无疑是一份宝贵的资源。Hibernate是一个开源的对象关系映射(ORM)框架,它极大地简化了Java...

    深入浅出HIbernate (加标签)1

    加了标签的《深入浅出HIbernate》,方便阅读和查找。

    深入浅出Hibernate(第二部分,共两部分).pdf

    深入浅出 Hibernate 电子书 中文

    《深入浅出Hibernate》读书笔记

    《深入浅出Hibernate》这本书是关于Java ORM框架Hibernate的深度解析。读书笔记主要涉及了实体对象的生命周期、实体对象的识别以及数据缓存这三大核心概念。 首先,实体对象的生命周期是Hibernate中至关重要的概念...

    《深入浅出Hibernate》.pdf

    《深入浅出Hibernate》这本书是针对初学者设计的,旨在帮助读者快速掌握Hibernate这一流行的Java对象关系映射(ORM)框架。Hibernate是一个强大的工具,它简化了Java应用程序与数据库之间的交互,通过提供一种抽象...

    深入浅出Hibernate.pdf

    尽管提供的“部分内容”并未直接涉及Hibernate的具体内容,但基于标题与描述中提到的“深入浅出Hibernate”,我们可以围绕Hibernate这一主题进行展开。 ### Hibernate简介 Hibernate是一个开源的对象关系映射...

    深入浅出Hibernate(PDF)夏昕.part 04

    深入浅出Hibernate(PDF)+夏昕(31.1M.pdf)

    深入浅出Hibernate源码

    菜单window -&gt; preference -&gt; Java -&gt; Build Path -&gt; User Librarys,分别建立名为Hibernate2,hibernate3,mysql-jdbc的用户库,分别包含对应的lib文件(如hibernate2包含hibernate-2.1目录下的hibernate2.jar及其lib...

    深入浅出hibernate,需要的下载

    《深入浅出Hibernate》这本书是Hibernate技术学习的重要参考资料,它为读者提供了全面、深入的Hibernate框架理解。Hibernate是一个开源的对象关系映射(ORM)框架,它简化了Java应用程序与数据库之间的交互,使得...

    深入浅出hibernate 完整pdf

    part1 一个2个 目前网上能找到最好的中文hibernate教程

Global site tag (gtag.js) - Google Analytics