hibernate应用中提升系统策略的措施(2)

2019-03-15 18:36

...... ..... 然后,load() 和 iterate() 永远也不会返回 Cat 和 DomesticCat 实例的代理。

Cat cat = (Cat) session.load(CatImpl.class, catid); Iterator iter = session.createQuery(\me='fritz'\).iterate(); Cat fritz = (Cat) iter.next(); 注意 list() 通常不返回代理。

这里,对象之间的关系也将被延迟载入。这就意味着,你应该将属性声明为 Cat,而不是 CatImpl。

有些方法中是不需要代理初始化的:

equals() 方法,如果持久类没有重载 equals() 方法。 hashCode():如果持久类没有重载 hashCode() 方法。 标志符的 getter 方法。

Hibernate 将会识别出那些重载了 equals()、或 hashCode() 方法的持久化类。

若选择 lazy=\而非默认的 lazy=\,我们可以避免类型转换带来的问题。然而,这样我们就需要编译期字节码增强,并且所有的操作都会导致立刻进行代理初始化。 21.1.4. 实例化集合和代理(Initializing collections and proxies)

在 Session 范围之外访问未初始化的集合或代理,Hibernate 将会抛出 LazyInitializationException 异常。也就是说,在分离状态下,访问一个实体所拥有的集合,或者访问其指向代理的属性时,会引发此异常。

有时候我们需要保证某个代理或者集合在 Session 关闭前就已经被初始化了。当然,我们可以通过强行调用 cat.getSex() 或者 cat.getKittens().size() 之类的方法来确保这一点。 但是这样的程序会造成读者的疑惑,也不符合通常的代码规范。

静态方法 Hibernate.initialized() 为你的应用程序提供了一个便捷的途径来延迟加载集合或代理。 只要它的 Session 处于 open 状态,Hibernate.initialize(cat) 将会为 cat 强制对代理实例化。同样,Hibernate.initialize(cat.getKittens()) 对 kittens 的集合具有同样的功能。

还有另外一种选择,就是保持 Session 一直处于 open 状态,直到所有需要的集合或代理都被载入。 在某些应用架构中,特别是对于那些使用 Hibernate 进行数据访问的代码,以及那些在不同应用层和不同物理进程中使用 Hibernate 的代码。 在集合实例化时,如何保证 Session 处于 open 状态经常会是一个问题。有两种方法可以解决此问题:

在一个基于 Web 的应用中,可以利用 servlet 过滤器(filter),在用户请求(request)结束、页面生成 结束时关闭 Session(这里使用了在展示层保持打开 Session 模式(Open Session in View)),当然,这将依赖于应用框架中异常需要被正确的处理。

在返回界面给用户之前,乃至在生成界面过程中发生异常的情况下,正确关闭 Session 和结束事务将是非常重要的, 请参见 Hibernate wiki 上的 \Session in View\模式,你可以找到示例。

在一个拥有单独业务层的应用中,业务层必须在返回之前,为 web 层“准备”好其所需的数据集合。这就意味着 业务层应该载入所有表现层/web 层所需的数据,并将这些已实例化完毕的数据返回。通常,应用程序应该为 web 层所需的每个集合调用 Hibernate.initialize()(这个调用必须发生咱 session 关闭之前);或者使用带有 FETCH 从句,或 FetchMode.JOIN 的 Hibernate 查询,事先取得所有的数据集合。如果你在应用中使用了 Command 模式,代替 Session Facade,那么这项任务将会变得简单的多。

你也可以通过 merge() 或 lock() 方法,在访问未实例化的集合(或代理)之前,为先前载入的对象绑定一个新的 Session。显然,Hibernate 将不会,也不应该自动完成这些任务,因为这将引入一个特殊的事务语义。

有时候,你并不需要完全实例化整个大的集合,仅需要了解它的部分信息(例如其大小)、或者集合的部分内容。

你可以使用集合过滤器得到其集合的大小,而不必实例化整个集合:

( (Integer) s.createFilter( collection, \ ).list().get(0) ).intValue() 这里的 createFilter() 方法也可以被用来有效的抓取集合的部分内容,而无需实例化整个集合:

s.createFilter( lazyCollection, \).setFirstResult(0).setMaxResults(10).list(); 21.1.5. 使用批量抓取(Using batch fetching)

Hibernate 可以充分有效的使用批量抓取,也就是说,如果仅一个访问代理(或集合),那么 Hibernate 将不载入其他未实例化的代理。批量抓取是延迟查询抓取的优化方案,你可以在两种批量抓取方案之间进行选择:在类级别和集合级别。

类/实体级别的批量抓取很容易理解。假设你在运行时将需要面对下面的问题:你在一个 Session 中载入了 25 个 Cat 实例,每个 Cat 实例都拥有一个引用成员 owner,其指向 Person,而 Person 类是代理,同时 lazy=\。如果你必须遍历整个 cats 集合,对每个元素调用 getOwner() 方法,Hibernate 将会默认的执行 25 次 SELECT 查询, 得到其 owner 的代理对象。这时,你可以通过在映射文件的 Person 属性,显式声明 batch-size,改变其行为:

... 随之,Hibernate 将只需要执行三次查询,分别为 10、10、 5。

你也可以在集合级别定义批量抓取。例如,如果每个 Person 都拥有一个延迟载入的 Cats 集合, 现在,Sesssion 中载入了 10 个 person 对象,遍历 person 集合将会引起 10 次 SELECT 查询,每次查询都会调用 getCats() 方法。如果你在 Person 的映射定义部分,允许对 cats 批量抓取,那么,Hibernate 将可以预先抓取整个集合。请看例子:

... 如果整个的 batch-size 是 3,那么 Hibernate 将会分四次执行 SELECT 查询, 按照 3、3、3、1 的大小分别载入数据。这里的每次载入的数据量还具体依赖于当前 Session 中未实例化集合的个数。

如果你的模型中有嵌套的树状结构,例如典型的帐单-原料结构(bill-of-materials pattern),集合的批量抓取是非常有用的。(尽管在更多情况下对树进行读取时,嵌套集合(nested set)或原料路径(materialized path)可能是更好的解决方法。) 21.1.6. 使用子查询抓取(Using subselect fetching)

假若一个延迟集合或单值代理需要抓取,Hibernate 会使用一个 subselect 重新运行原来的查询,一次性读入所有的实例。这和批量抓取的实现方法是一样的,不会有破碎的加载。 21.1.7. Fetch profile(抓取策略)

Another way to affect the fetching strategy for loading associated objects is through something called a fetch profile, which is a named configuration associated with the org.hibernate.SessionFactory but enabled, by name, on the org.hibernate.Session. Once enabled on a org.hibernate.Session, the fetch profile will be in affect for that org.hibernate.Session until it is explicitly disabled.

So what does that mean? Well lets explain that by way of an example which show the different available approaches to configure a fetch profile:

例 21.1. Specifying a fetch profile using @FetchProfile

@Entity @FetchProfile(name = \ @FetchProfile.FetchOverride(entity = Customer.class, association = \ }) public class Customer { @Id @GeneratedValue private long id; private String name; private long customerNumber; @OneToMany private Set orders; // standard getter/setter ... }

例 21.2. Specifying a fetch profile using outside node

... ...


hibernate应用中提升系统策略的措施(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:郭伟+基于pq分解模型的静态安全分析 - 图文

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: