Hibernate懒加载

 

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中,具体选择哪种抓取策略的机制是和选择 单值关联或集合关联相一致的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值