当前位置: 首页 > 图文教程 > Java技术 > 数据库持久层 > 数据库持久层:小编浅谈hibernate中抓取策略
传统的关系数据访问利用内连接和外连接检索相关的实体,用单个SQL查询抓取对某个计算所需要的所有数据。一些原始的ORM实现分开抓取数据,多次请求小块的数据,应用程序作为响应也会多次导航持久对象图。这种方法不能有效利用关系数据库的连接能力。实际上,这种数据访问策略将来很难扩展。ORM中的一个最困难的问题—可能是最困难的—是提供对关系数据库的有效访问,鉴于应用程序喜欢把数据当成对象图看待。
对于我们经常开发的多种应用程序(多用户,分布式,web 和企业应用),检索对象时多次往返于数据库是不可取的。因此,我们讨论的工具比传统的工具更强调ORM中的R(关系)。
有效地抓取对象图的问题已经通过在关联映射的元数据中指定关联级抓取策略解决了。
这种方法存在的问题是每段代码使用一个需要不同集合的相关对象的实体。但是这是不够的。我们需要的是支持细粒度的运行时关联抓取策略。Hibernate 两者都支持,允许在映射文件中指定默认的抓取策略,然后在代码运行时重载。
Hibernate对于任何关联允许在四种抓取策略中选择,在关联元数据和运行时:
立即抓取—立即抓取关联的对象,使用连续的数据库读(或缓存查找)。
延迟抓取—当第一次访问时,“延迟”抓取相关的对象或集合。这个结果在对数据库
的新请求中(除非缓存了相关的对象)。
提前抓取—相关的对象或集合同拥有它们的对象一起抓取,使用SQL外连接,不需
要额外的数据库请求。
批量抓取—在访问延迟关联时,这种方法通过检索一批对象或集合来提高延迟抓取
的性能。(批量抓取也用来提高立即抓取的性能。)
让我们仔细看看每种抓取策略。
立即抓取
立即的关联抓取发生在从数据库中检索实体然后立即在下一个对数据库或缓存的请求中
检索另一个(或一些)相关的实体的时候。立即抓取通常不是有效的抓取策略除非希望关联
的实体一直被缓存。
延迟抓取
当客户请求数据库中的实体及其相关的对象图时,通常不必检索每个(非直接的)关联
对象的整个对象图。你不希望立即把整个数据库装载到内存中,例如,装载单个Category 不
应该触发装载这个目录的所有Item。延迟抓取能够让你决定第一次访问数据库时装载多少对象图,并且与其关联的对象只有在第一次访问时才装载。延迟抓取是对象持久化中的基本内容,而且是取得可接受性能的第一步。我们推荐在开始的时候把映射文档中所有的关联映射为延迟(或可能是批量延迟)抓取。这种策略然后被强制提前抓取发生的查询重载。
提前(外连接)抓取
延迟关联抓取能够帮助减少数据库装载,而且通常是一种好的默认策略。然而,这在性
能优化发生前有点盲目猜测。提前抓取让你显式地指定哪些关联的对象应该同引用它们的对象一起装载。Hibernate 然后在单个数据库请求中使用SQL的OUTER JOIN 返回关联的对象。Hibernate的性能优化通常包括针对某些事务明智地使用提前抓取。因此,即使在映射文件中声明了默认的抓取策略,在运行时对于某个HQL或条件查询指定使用这种策略更普遍。
批量抓取
批量抓取不是严格的关联抓取策略,它是帮助提高延迟(或立即)抓取性能的一种技术。
通常,当装载对象或集合的时候,SQL的WHERE 子句指定对象的标识符或拥有集合的对象。如果开启了批量抓取,Hibernate看起来知道什么会在当前session 中引用其它代理实例或未初始化的集合,尽量通过在WHERE 子句中指定多个标识符值来同时装载这些对象。
我们不是这种方法的热心者,提前抓取几乎一直是更快的。批量抓取对那些希望用Hibernate 达到可接受的性能而不用想太多关于要执行的SQL 的经验不足的用户很有用。(注意,你可能很熟悉批量抓取,因为它已经被许多EJB2 引擎使用)。
评论 (0) All