• HQL进阶


    1、HQL查询性能优化

      1.1、避免or操作

        1.1.1、where子句包含or操作,执行时不使用索引

          from Hose where street_id='1000' or street_id='1001'

        1.1.2、可以使用in条件来替换

          from Hose where street_id in('1000','1001')

      1.2、避免使用not

        1.2.1、where子句包含not关键字,执行时该字段的索引失效

          from Hose h where not(h.price>1800)

        1.2.2、使用比较运算符替换not

          from Hose h where h.price<=1800

      1.3、避免like的特殊形式(查询时尽可能少使用like)

      1.4、避免having子句(尽可能在where 子句中指定条件)

      1.5、避免使用distinct(在不要求或允许冗余时,应避免使用distinct)

    2、数据加载方式

      2.1、即时加载

        <hibernate-mapping>
            <class name="cn.jbit.houserent.bean.District" table="district">
                <id name="id" type="java.lang.Integer">
                    <column name="id" />
                    <generator class="native" />
                </id>
              <property name="name" type="java.lang.String">
                  <column name="district_name" length="50" not-null="true" />
              </property>
            <!--   -->
              <set name="streets" table="street" cascade="all" inverse="true" lazy="false">
                <key>
                    <column name="district_id" not-null="true" />
                </key>
                <one-to-many class="cn.jbit.houserent.bean.Street" />
            </set>
        </class>
    </hibernate-mapping>

       SessionFactory sf=null;

       Session s=null;

       List<district> list=null;

       try{

        sf=new Configuration().configure().buildSessionFactory();

        s=sf.openSession();

        Query q=s.createQuery("from District where id='1004'");

        list=q.list();

        for(District d:list){

          System.out.println("区名"+d.getName());

          Set streets=d.getStreets();

          System.out.println("街道数量"+streets.size());

       }

      }case(HibernateException e){e.printStackTrace}finally{

        s.close();

        sf.close();

     }

      2.2、延迟加载

        延迟加载就是当真正需要数据的时候,才真正执行数据加载操作

        类级别的默认加载策略为延迟加载

        hibernate提供了:

            对实体对象的延迟加载(为实体设置延时加载,即设置<class>元素的lazy属性为true)

            集合的延迟加载

            属性的延迟加载(1、Hibernate 3 中,引入的新特性——属性的延迟加载
    2、适用于二进制大对象、字符串大对象以及大容量组件类型的属性)

        <hibernate-mapping>
            <class name="cn.jbit.houserent.bean.District" table="district">
                <id name="id" type="java.lang.Integer">
                    <column name="id" />
                    <generator class="native" />
                </id>
              <property name="name" type="java.lang.String">
                  <column name="district_name" length="50" not-null="true" />
              </property>
            <!--   -->
              <set name="streets" table="street" cascade="all" inverse="true" lazy="true">
                  <key>
                      <column name="district_id" not-null="true" />
                  </key>
                  <one-to-many class="cn.jbit.houserent.bean.Street" />
              </set>
          </class>
      </hibernate-mapping>

       //实体延迟加载

       SessionFactory sf=null;

       Session s=null;

       try{

        sf=new Configuration().configure().buildSessionFactory();

        s=sf.openSession();

        User u=(User)s.load(User.class,new Integer("1000"));

        System.out.println("获取用户id为1000的用户");

        System.out.println("用户名:"+u.getName());

      }case(HibernateException e){e.printStackTrace}finally{

        s.close();

        sf.close();

     }

     //属性延迟加载

      <class name="cn.jbit.houserent.bean.House" table="house">
          <!--省略其他配置-->
          <property name="description" type="text" lazy="true">
              <column name="description"/>
          </property>
      </class>

       SessionFactory sf=null;

       Session s=null;

       try{

        sf=new Configuration().configure().buildSessionFactory();

        s=sf.openSession();

        Query q=s.createQuery("from Hose h where h.price=2300");

        System.out.println("获取价格为2300元的房屋信息");

        List<Hose>list=q.list();

        for(Hose h:list){

          System.out.println("标题:"+h.getTitle());

          System.out.println("描述:"+h.getDescription());

        }

      

      }case(HibernateException e){e.printStackTrace}finally{

        s.close();

        sf.close();

     }

      2.3、list()方法和iterate()方法

        sessionFactory = new Configuration().configure().buildSessionFactory();
        session = sessionFactory.openSession();
        Query query = session.createQuery("from House as h ");
        System.out.println("使用iterate()方法查询数据");
        Iterator<House> it = query.iterate();
        while(it.hasNext()){
           House house = it.next();
           System.out.println("标题:"+house.getTitle());
        }
        System.out.println("-------------------"); 
        System.out.println("使用list()方法查询数据");  
        List<House> result = query.list();
        for(House house:result){
           System.out.println("标题:"+house.getTitle());
      }

       2.3.1、使用list()方法获取查询结果,每次发出一条查询语句,获取全部结果

       2.3.2、使用iterate()方法获取查询结果,先发出一条sql语句用来查询满足条件的id;然后依次按这些id查询记录,也就是要执行n+1条sql语句

    3、HQl联接查询

      3.1、内联接:inner join

        3.1.1、最典型、最常用的联接查询

        3.1.2、两个表存在主外键关系时通常会使用内联接查询

      3.2、外联接:

        3.2.1、左外联接:left join或left outer join

        3.2.2、右外联接:right join 或right outer join

        3.2.3、完整外联接:full join或 full outer join

      3.3、内联接

        from Entity inner join [fetch] Entity.property

        sessionFactory = new Configuration().configure().buildSessionFactory();
        session = sessionFactory.openSession();
        Query query = session.createQuery("from District d inner join d.streets s");
        List result = query.list();
        Iterator it = result.iterator();
        while(it.hasNext()){
            Object[] results = (Object[]) it.next() ;
            System.out.println("数据的类型:");
          for (int i=0;i<results.length;i++){
                System.out.println(results[i]);
         }
    }

      3.4、左外联接

        from Entity left join [fetch] Entity.property

      3.5、右外联接

        from Entity right join [fetch] Entity.property

    4、命名查询

      <hibernate-mapping>
          <class name="cn.jbit.houserent.bean.User" table="users">
            <!--省略其他配置-->
          </class>
          <query name="loginUser">
              <![CDATA[
                  from User u where u.name =:name and u.password =:password
              ]]>
          </query>
      </hibernate-mapping>

      Query q=session.getNamedQuery("loginUser");

      QueryUser qu=new QueryUser();

      qu.setName("admin");

      qu.setPassword("123");

      q.setProperties(qu);

      List list=q.list();

      Iterator it=list.iterator();

      if(it.hasNext()){

        User u=(User)it.next();

        System.out.println("欢迎"+u.getUserName());

      }

    <query>元素用于定义一个HQL 查询语句,它和<class>元素并列
    以<![CDATA[HQL]]>方式保存HQL 语句
    在程序中通过Session 对象的getNamedQuery()方法获取该查询语句

    5、本地SQL查询

      Hibernate 对本地SQL查询提供了内置的支持
        Session 的createSQLQuery()方法返回SQLQuery 对象
        SQLQuery接口继承了Query接口
        SQLQuery接口的addEntity()方法将查询结果集中的关系数据映射为对象
        通过命名查询实现本地SQL查询
          使用<sql-query>元素定义本地SQL 查询语句
          与<class>元素并列
          以<![CDATA[SQL]]>方式保存SQL 语句
          通过Session 对象的getNamedQuery()方法获取该查询语句

    6、本阶段总结

      HQL优化方法如下

        避免or操作

        避免使用not

        避免like的特殊形式

        避免having子句

        避免使用distinct

      数据延迟加载分为以下三类

        集合类型的延迟加载

        实体对象的延迟加载

        属性延迟加载

      HQl联接查询包括以下几种

        内联接

        外联接:左外联接、右外联接、完整外联接

      

      命名查询

      本地SQL查询

      

  • 相关阅读:
    程序的机器级表示(一)
    virtual memory(1)
    Python定义参数数量可变的method的问题
    存储器结构层次(四)
    CAShapeLayer
    cell
    远程服务器推送
    keyboad
    search搜索
    Cocoopod
  • 原文地址:https://www.cnblogs.com/lanliying/p/3180597.html
Copyright © 2020-2023  润新知