Hibernate懒加载
懒加载
通过asm和cglib两个包实现;Domain是非fina的。
1、session.load懒加载。
2、one-to-one(元素)懒加载:
必须同时满足下面三个条件时才能实现懒加载
(主表不能有constrained=true,所以主表没有懒加载)
Lazy!=false 2)constrained=true 3)fetch=select
3、one-to-many(元素)懒加载:1)lazy!=false 2)fetch=select
4、many-to-one(元素):1)lazy!=false 2)fetch=select
5、many-to-many (元素):1)lazy!=false 2)fetch=select
6、能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,活用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,在访问懒加载的对象将出现异常。
抓取策略(Fetch strategies)
抓取策略(feching strategy)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hinertia如何获取关联对象的策略。抓取策略可以在O/R映射的原数据中声明,也可以在特定的HQL或条件查询(Criteria Query)中重载声明。
Hibernate3定义了如下几种抓驱策略:
l 连接抓取(Join fetching)-Hibernate通过在select语句使用outer join(外连接)来获得对象的关联实例或者关联集合。
l 查询抓取(Select fetching)-另外发送了一条select语句抓取当前对象的关联实体或集合。除非你显式的指定lazy=“false”禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
l 子查询抓取(Subselect fetching)-另外发送一条select语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy=“false”禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
l 批量抓取(Batch fetching)-对查询抓取的优化方案,通过指定一个主键或外键列表Hibernate使用单条select语句获取一批对象实例或集合。
Hibernate会区分下列各种情况:
l Immediate fetching,立即抓取-当宿主被加载时,关联、集合或属性被立即抓取。
l Lazy collection fetching,延迟集合抓取-知道应用程序对集合进行了一次操作时,集合才被抓取。(对集合而言这是默认行为。)
l Proxy fetching,代理抓取-对返回单值的关联而言,当某个方法被调用,而非对其关键字进行get操作时才抓取。
l Lazy attribute fetching,属性延迟加载-对属性或返回单值的关联而言,当其实例变量被访问的时候进行抓取(需要运行时字节码强化)。这一方法很少是必要的。
这里有两个正交的概念:关联何时被抓取,以及被如何抓取(会采用设么样的SQL语句)。不要混淆他们!我们使用抓取来改善性能。我们使用延迟来定义一些契约,对某特定类的某个托管的实例,知道有那些数据时可用的。
操作延迟加载的关联
默认情况下,Hibernate3对集合使用延迟select抓取,对返回单值的关联使用延迟代理抓取。对几乎是所有的应用而言,其绝大多数的关联,这种策略都是有效的。
注意:假若你设置了hibernate.default_batch_fetch_size,Hibernate会对延迟加载采取批量抓取优化措施(这种优化也可能会在更细化的级别打开)。
然而,你必须了解延迟抓取带来的一个问题。在一个打开的Hibernate session上下文之外调用延迟集合会导致一次意外。比如:
s=session.openSession();
Transaction tx=s.beginTransaction();
User u=(User) s.createQuery(“from User u where u.name=:userName”).seString(“userName”,userName),uniqueResult();
Map permissions = u.getPermissions();
Tx.commit();
s.close();
Integer accessLevel = (Integer) permissions.get(“accounts”);//Error!
在Session关闭后,permessions集合将是为实例化的、不再可用,因此无法正常载入其状态。Hibernate对托管对象不支持延迟实例化这里的修改方法是:将permissions读取数据的代码 移到tx.commit()之前。
除此之外,通过对关联映射指定lazy=“false”,我们也可以使用非延迟的集合或关联。但是,对绝大部分集合来说,更推荐使用延迟凡是抓取数据。如果在你的对象模型中定义了太多的非延迟关联,Hibernate最终几乎需要在每个事物中载入整个数据库到内存中!
但是,另一方面,在一些特殊的事物中,我们也经常需要使用到连接抓取(他本身上就是非延迟的),以代替查询抓取。下面我们将会很快明白如何具体的定制Hibernate中的抓取策略。在Hibernate3中,具体选择哪种抓取策略的机制是和选择 单值关联或集合关联相一致的。

被折叠的 条评论
为什么被折叠?



