现在的位置: 首页 > 综合 > 正文

Hibernate 性能优化

2013年08月31日 ⁄ 综合 ⁄ 共 4989字 ⁄ 字号 评论关闭

一、应用<class> 标签的<dynamc-insert> 和<dynamic-update> 属性

     问题:没有使用<dynamc-insert> 和<dynamic-update> 属性,update或者insert 发起的hql 默认会更新所有的字段。

             比如:Book book = hibernateDao.load(id);
       book.setName("chen");
      后台HQL  update book set name=?,price=?,date=? where id =?;
      设置<dynamc-insert> 和<dynamic-update> 属性为true 会根据实际需要设置新增或者更新的字段,
      后台HQL    update book set name=? where id=?;

 

二、延迟加载

   (1)、实体对象的延迟加载

    配置文件设置

      <hibernate-mapping>

                        <class name="com.cn...Tuser"

                                    table="TUSER"

                                    lazy=true>

      </hibernate-mapping>

    Tuser user=session.load(Tuser.class,new Integer(2))       ----(1)

    user.getName()                                                                  ------(2)

      配置文件 lazy=true  设置为延迟加载,只有当客户当程序真真调用实体类的取值方法(执行(2)),   Hibernate  才会执行数据库查询操作。在执行(1)过程中其实首先是构造了一个代理类,把目标类放在代理类的target属性中,且其所有的属性都是null,日志没有打印,说明还没执行SQL语句。

而如果是lazy=false 则程序执行到(1)的时候就有日志打印,说明:Hibernate已经从库表中取出记录,构造了一个完整的Tuser对象。

      (2)、集合的延迟加载

            配置文件

            <hibernate-mapping>

                        <class name="com.cn...Tuser"

                                    table="TUSER"

                         >

                        <set name="address"

                                table="TUSER"

                                layz=true

                                casecade="all"  //所有的操作都进行关联操作 save update delete

                                inverse="false">//维护两个实体的关系,false自己维护,true对方维护

                            <key column="TUSER_ID"></key>

                            <one-to-many class="cn.com...ADDRESS"></one-to-many>

                         <set>

                    </hibernate-mapping>

                   eg:

                  Tuser user=(Tuser)session.load(Tuser.class,new Integer(2))

                   set addSet=user.getAddress()                             -------(1)

                   Iterator iterator=addSet.ietrator();                       --------(2)

                   while(iterator.hasNext()){}

                 程序执行到(1) 时,address数据尚未读入,只是一个net.sf.hibernate.collection.Set实例

                 只有在执行到(2)时数据才真真载入,这就是延迟加载的集合延迟加载机制。

         (3)属性的延迟加载

                 <hibernate-mapping>

                        <class name="com.cn...Tuser"

                                    table="TUSER"

                         >

                         <property

                                 name="resume"

                                 type="java.lang.Integer"

                                column="RESUME"

                                lazy="true"

                          />

                </hibernate-mapping>

 

            while(iterator.hasNext()){

                     user.getName();

                    user.getResume();

              }

        日志会执行两条SQL语句,第一条加载非延迟加载字段,第二条加载了延迟加载字段

三、抓取策略
    1、默认的fetch策略是 select
    <manyh-to-one name="classes" column="classesid" fetch="select"/> 同理 集合上也是<set name="students" cascade="all" fetch="select"><key column="classid"/><one-to-many class="cn.com.student"/></set>
    例外发送一条sql语句抓取当前对象关联实体或集合,总共发生两天sql语句
    2、 fetch="join",总共发生一条sql语句,通过left out 左外连接直接加载关联对象或集合,在这种情况下lazy 会失效。
    3、 集合fetch="subselect"  主要是对hql起作用
        List list = session.createQuery("select c from classes c where c.id in(1,2,3) ").list();
        for (Iterator iterator = list.iterator(),iterator.hasNext()) {
   Classes classes = (Classes)iterator.next();
   System.out.println("classes.name="+classes.getName());
   for (Iterator iterator1 = classes.getStudents().iterator();iterator1.hasNext()){
   Student student = (Student)iterator1.next();
    System.out.println("student.name="+student.getName());
   }
  }
 对于hql one-to-many 上设置 fetch="select" 则每次查出一个班级都会再发一条sql语句查出对应的班级
               日志:Hibernate:select classes0_.id from t_class classes0_ where classes0_.id in(1,2,3);
                     classes.name="班级0";
                     Hibernate:select student0_.id,student0_.name from t_student student0_ where student0_.classesid=? //查出第一个班级的
 而如果设置fetch = "subSelect" 则会通过子查询把班级对应的学生一块查出.
                     Hibernate:select student0_.id,student0_.name from t_student student0_  where student0_.classesid in(select classes0_.id from t_class                                classes0_ where classes0_.id in(1,2,3));
    4、批量加载实体 batch-size 有组与优化性能
   List list = session.createQuery("select s from Student where s.id in(:ids)").list()
                 .setParameterList("ids",new Object[]{1,3,4,5,11,6,7,8,9,10});
                 .list();
    for (Iterator iterator = list.iterator();iterator.hasNext()){
   Student student = (Student)iterator.next();
            System.out.println("student.name="+student.getName());
   System.out.println("student.classes.name="+student.getClasses.getName());
     }
 每循环一次,都会发一条sql 语句,把这个学生对于的班级查询出来,所以会发10条这样的sql
   日志:select classes0_.id,classes0_.name from t_classes classes0_ where classes0_.id=?
   在Classes.hbm.xml文件里 <Class name="ClassesImpl" table="t_classes" batch-size=5>
   日志:select classes0_.id,classes0_.name from t_classes classes0_ where classes0_.id in(?,?,?,?,?);
     5、批量加载集合
           同理在<set name="students" batch-size="5" cascade ="all">
             <key column="classesid">
                          <one-to-many classes="cn.com.Student"/>
                  </set>

抱歉!评论已关闭.