`
huliangyu
  • 浏览: 6688 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

hibernate3 many-to-one 延迟加载

 
阅读更多
hibernate lazy策略可以使用在:

lazy="proxy",也是延迟加载的一种,需要满足以下条件;

比如说User和Group是many-to-one的关系,User中有一个类型为Group的属性group,  
  若你想要载入一个User时,它的Group属性group要延迟载入,  
   
  条件一:   必须为Group类定义proxy,这个proxy一般可以定义为两种  
      1   Group类本身  
      2   一个被Group类实现的,且包含了Group类的所有业务方法的接口,这种做法可以克服第一种做法的一些缺点,但会比较麻烦,因为要定义一个接口嘛。  
   
  条件二:   映射文件中这个<many-to-one>的outer-join要定义为    "false"
   









* <class>标签上,可以取值:true/false ,在hibernate3以上版本,默认是true
* <property>标签上,可以取值:true/false需要类增强工具
* <set><list>标签上,可以取值:true/false/extra
* <one-to-one><many-to-one>单端关联上,可以取值:false/proxy/no-proxy

lazy概念:只有真正使用该对象时,才会创建,对于hibernate而言,正真使用的时候才会发出sql

hibernate支持lazy策略只有在session打开状态下有效




=====================================================

1. <class>标签上:

hbm

group.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="Group" table="group5" lazy="true" > //lazy,默认true,可不写
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native" />         
        </id>
        <property name="name" column="name" length="50" type="java.lang.String" />
       
    </class>

</hibernate-mapping>

测试用例:

public class LazyTest extends TestCase {

public void testLoad1(){
   Session session = null;
   Transaction ta = null;
   try{
    session = HibernateUtil.getSession();
    ta = session.beginTransaction();

    Group g2 = (Group) session.load(Group.class, 1); //还没发出sql,lazy起延迟作用,若lazy=false,则发出sql
//    Group g2 = (Group) session.get(Group.class, 1); //不支持lazy
    System.out.println("group.id=" + g2.getId()); //还没发出sql,
    System.out.println("group.name=" + g2.getName()); //发出sql
    ta.commit();
   }catch(Exception e){
    e.printStackTrace();
    if(ta != null){
     ta.rollback();
    }
   }finally{
    //关闭session, user变为detached离线对象
    HibernateUtil.closeSession(session);
   }
   //System.out.println("group.name=" + g2.getName()); //hibernate支持lazy策略只有在session打开状态下有效,所以此出Exception
}

}





<class>标签上的lazy特性只对普通属性起作用

<class>标签上的lazy不会影响到单端关联上的lazy特性

=========================================

2.<set><list>标签上,可以取值:true/false/extra,默认是true

hbm.xml

Classes.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.zd.model">
    <class name="Classes" table="classes" >
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native" />
        </id>
        <property name="name" column="name" type="java.lang.String" />
       <set name="students" lazy="true"> //可不配lazy,因默认是true
            <key column="class_id" />
            <one-to-many class="com.zd.model.Student" />
        </set>
    </class>

</hibernate-mapping>

测试用例:

public void testLoad1(){
   Session session = null;
   Transaction ta = null;
   try{
    session = HibernateUtil.getSession();
    ta = session.beginTransaction();
    Classes c = (Classes) session.load(Classes.class, new Integer(2)); //没有sql
    System.out.println("Class.name=" + c.getName());//发出一条sql,但不查 set
    Set stuSet = c.getStudents();//没有发出查询sql,不是统计sql
    //System.out.println(stuSet.size());//发出查询sqlsql
    if(stuSet != null && !stuSet.isEmpty()){//发出查询sqlsql
     for(Iterator it = stuSet.iterator(); it.hasNext();){
      Student s = (Student) it.next();//若没有.size(),isEmpty(),就在这边发出sql
      System.out.println("student.name=" + s.getName());
     }
    }
    ta.commit();
   }catch(Exception e){
    e.printStackTrace();
    if(ta != null){
     ta.rollback();
    }
   }finally{
    //关闭session, user变为detached离线对象
    HibernateUtil.closeSession(session);
   }
 
}

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes classes0_ where classes0_.id=?
Class.name=Java Class
Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
2
student.name=z3
student.name=l4



若<set name="students" lazy="false"> //不延迟加载, 马上加载

则在

System.out.println("Class.name=" + c.getName());// 就发出2条查询语句了。

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes classes0_ where classes0_.id=?
Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
Class.name=Java Class
student.name=l4
student.name=z3



若<set name="students" lazy="extra"> //和true差不多,只是在写set.size()时,发出selcet count的sql语句,比true好一些。

测试用例:

public void testLoad1(){
   Session session = null;
   Transaction ta = null;
   try{
    session = HibernateUtil.getSession();
    ta = session.beginTransaction();
    Classes c = (Classes) session.load(Classes.class, new Integer(2));
    System.out.println("Class.name=" + c.getName());
    Set stuSet = c.getStudents();
   System.out.println(stuSet.size());
    if(stuSet != null && !stuSet.isEmpty()){
     for(Iterator it = stuSet.iterator(); it.hasNext();){
      Student s = (Student) it.next();
      System.out.println("student.name=" + s.getName());
     }
    }
    ta.commit();
   }catch(Exception e){
    e.printStackTrace();
    if(ta != null){
     ta.rollback();
    }
   }finally{
    //关闭session, user变为detached离线对象
    HibernateUtil.closeSession(session);
   }
 
}

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes classes0_ where classes0_.id=?
Class.name=Java Class
Hibernate: select count(id) from student where class_id =?
2
Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
student.name=z3
student.name=l4



===============================================

3.<one-to-one><many-to-one>单端关联上,可以取值:false/proxy/no-proxy,默认是proxy(代理),延迟加载作用

hbm.xml

User.hbm.xml 多的一端

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="User" table="user1" >
        <id name="id" column="user_id" type="java.lang.Integer">
            <generator class="native" />
        </id>
        <property name="name" length="50" type="java.lang.String" />
        <many-to-one name="group" column="group_id" lazy="proxy"></many-to-one> //可不写,默认是proxy
    </class>

</hibernate-mapping>

测试用例:

public void testGet1(){
   Session session = null;
   Transaction ta = null;
   User user = null;
   try{
    session = HibernateUtil.getSession();
    ta = session.beginTransaction();
    user = (User)session.load(User.class, new Integer(3)); //无sql
    System.out.println("user.name=" + user.getName()); //有一条sql
    Group group = user.getGroup();//无sql
    System.out.println("group.name=" + group.getName());//有一条sql
    ta.commit();
   }catch(Exception e){
    e.printStackTrace();
    ta.rollback();
   }finally{
    //关闭session, user变为detached离线对象
    HibernateUtil.closeSession(session);
   }
 
}

若<many-to-one name="group" column="group_id" lazy="false"></many-to-one>

不延迟加载,立即加载,

System.out.println("user.name=" + user.getName()); //发出2条sql语句



==========================================

hibernate 中的 lazy="proxy" 和 lazy="no-proxy" 到底是什么意思?

举个例子吧:
Child <- many-to-one ->Parent

class Child {
private Parent parent;

public Parent getParent (){
return this.parent;//访问了实例变量
}

}

class Parent {
private String name;

public String getName(){
return this.name;//访问了实例变量
}

public void f(){
System.out.println("invokeing f()");//没有访问实例变量
}
}

如果 many-to-one 的lazy设为proxy,当child.getParent().getName()或child.getParent().f()时,parent都会被抓取,若设为no-proxy,调用child.getParent().f()时,parent是不会被抓取的,同时这种方式需要编译时字节码增强,否则和proxy没区别。 (注:测试发现真和proxy一样,不能理解 编译时字节码增强,要再哪修改,或是什么条件?)



如果设置了 lazy="proxy",就   ,当通过 child 来调用其关联的 parent, 如果调用 parent 类中定义的任何方法,都会抓取 parent (所谓的抓取是不是就是从数据库查询,执行一次 select ?)
如果设置了 lazy="no-proxy" ,只有调用 parent 类中牵涉到类变量的方法,才会抓取 parent,否则,就像调用 f(), 不会抓取 parent 

."编译时字节码增强" 是什么意思?
"字节码增强"分编译期和运行期2种,编译期是修改java类编译后的class字节码文件,在上面附加“增强”操作。(不明白why?)



================

lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。lazy="no-proxy"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 lazy="false"指定此关联总是被预先抓取。注意,如果constrained="false", 不可能使用代理,Hibernate会采取预先抓取!
分享到:
评论

相关推荐

    Hibernate one to many(many to one) 配置

    标题"Hibernate one to many(many to one) 配置"涉及到的是关系型数据库在Java中的持久化框架Hibernate中的两种关联映射关系:一对一(One-to-One)和多对一(Many-to-One)。在数据库设计中,这种关系很常见,例如...

    day36 07-Hibernate抓取策略:many-to-one上的抓取策略

    今天我们要讨论的是Hibernate框架中的一个关键概念——抓取策略,特别是针对"many-to-one"关系的抓取策略。这篇博客将深入剖析这个主题,帮助你更好地理解和应用Hibernate。 Hibernate是Java领域中最流行的对象关系...

    hibernate-release-5.0.7.Final.zip官方

    &lt;one-to-many class="Order"/&gt; ``` ```java @Entity public class User { @Id private Long id; private String name; @Fetch(FetchMode.JOIN) @OneToMany(mappedBy = "user") private List&lt;Order&gt;...

    Hibernate延迟加载以及利用Spring

    比如在给定的部分内容中,`&lt;many-to-one name="dept" class="com.sxy.dao.Dept" fetch="select" lazy="proxy"&gt;` 表示了部门(Dept)与员工(Emp)之间存在多对一关系,并且配置了延迟加载。 - `lazy="proxy"`:表示...

    hibernate延迟加载解决

    ### Hibernate延迟加载详解 #### 一、什么是延迟加载? 延迟加载是一种优化技术,在软件开发中广泛应用于各种场景,尤其在数据库交互中尤为重要。其核心思想是仅在确实需要某个资源时才加载它,而非一开始就加载...

    Hibernate延迟加载

    4. 单端关联(One-to-one, many-to-one)的延迟加载:`&lt;one-to-one&gt;`和`&lt;many-to-one&gt;`元素的`lazy="proxy"`、`lazy="false"`或`lazy="noproxy"`可以控制关联对象的延迟加载行为。`lazy="proxy"`会在访问关联对象时...

    Hibernate的延迟加载

    ### Hibernate的延迟加载详解 #### 实体对象的延迟加载 延迟加载是Hibernate中一项关键的优化技术,旨在减少不必要的数据库交互,从而提升应用程序的性能。其实现原理在于,只有当确实需要访问某个对象或集合的...

    Hibernate 延迟加载

    ### Hibernate延迟加载详解 #### 什么是Hibernate延迟加载? 在探讨Hibernate延迟加载之前,我们先简要回顾一下Hibernate框架。Hibernate是一种流行的Java持久层框架,它提供了对象关系映射(ORM)的功能,允许...

    Hibernate-api Hibernate文档

    - Get()与Load():根据主键获取对象,Load()延迟加载。 六、Querying 1. HQL:面向对象的查询语言,类似于SQL,但操作对象而非记录。 2. Criteria API:更加面向对象的查询方式,通过构建Criteria对象来构建查询。 ...

    hibernate延迟加载技术详细解

    ### Hibernate 延迟加载技术详解 #### 一、概述 在 Hibernate 框架中,延迟加载(Lazy Loading)是一种非常重要的优化技术,它能够有效地减少数据库查询次数,提高应用性能。通常,在多对多或者一对多的关系中,...

    常见hibernate面试题

    - Hibernate3增加了属性的延迟加载,只有在实际访问属性时才会加载数据。 6. **类之间的关系映射** - 一对多(one-to-many):通过配置`&lt;set&gt;`或`&lt;list&gt;`标签来实现。 - 多对一(many-to-one):使用`&lt;many-to-...

    hibernate_6映射关系之one2many.zip_hibernate

    在Java的持久化框架Hibernate中,`One-to-Many`映射关系是对象关系映射(ORM)中常见的一种关联类型。它表示一个实体("One"端)与多个其他实体("Many"端)之间的关系。例如,一个学生可以有多个课程,一个老师可以...

    Hibernate 延迟加载剖析与代理模式应用

    &lt;one-to-many class="Address"/&gt; ``` #### 四、代理模式的应用 在实现延迟加载的过程中,Hibernate利用了代理模式。代理模式是一种结构型设计模式,它通过引入代理对象来控制对真实对象的访问。在这种模式下,...

    Hibernate延迟加载介绍.doc

    三、属性的延迟加载(Hibernate 3及以上版本) 在Hibernate 3中,引入了属性级别的延迟加载。这意味着除了对象和集合外,单个属性也可以实现延迟加载。例如,如果User类有一个大文本字段`description`,我们可以...

    hibernate延迟加载

    从 Hibernate 3 开始,除了实体对象和集合之外,还可以实现对属性的延迟加载。这使得可以在实体对象已经加载的情况下,只加载需要的特定属性,进一步提高了性能。 ##### 配置示例 ```xml &lt;hibernate-mapping&gt; ...

    hibernate-mapping

    例如,`&lt;one-to-one&gt;`、`&lt;many-to-one&gt;`、`&lt;one-to-many&gt;`和`&lt;many-to-many&gt;`元素分别对应这四种关系。关联映射通常涉及外键的处理和级联操作。 5. 注解方式的Mapping 除了XML映射,Hibernate还支持注解方式的映射...

    Hibernate 的关联映射

    "Hibernate的关联映射"是Hibernate中的核心概念之一,用于模拟数据库中的关系,包括一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)四种关系。现在,让我们详细探讨...

Global site tag (gtag.js) - Google Analytics