Hibernate查询总结

来源:互联网 发布:java aes 加密 cfb 编辑:程序博客网 时间:2024/06/06 07:07

   1:使用Session的createQuery()方法
     如:List cats = session.createQuery(
                       "from Company c where c.creationDate <?")
                       .setDate(0, date)
                       .list();
     一个查询通常在调用list方法时被执行,执行结果会完全加载进内存中的一个集合中。如果查询结果返回的是一个
     持久对象,则可以用Query的uniqueResult()方法。
   
    2:迭代获取结果
    iterator迭代查询结果:
      Session session = sessionFactory.openSession();
      Iterator iter = session.createQuery(
                       "from Company c order by c.creationDate").iterator();
                     
      while(iter.hasNext()) {
           Company c = (Company)iter.next();
           System.out.println(c.getName());
      }
     
      list迭代查询结果:
      Session session = sessionFactory.openSession();
      List result = session.createQuery(
                    "from Company c order by c.creationDate").list();
      Iterator iter = result.iterator();
      while(iter.hasNext()) {
          Company c = (Company)iter.next();
          System.out.println("Result:" + c.getName());
      }
      iterator()方法相对于list()方法而言,会首先通过HQL生成查询对象标识符的SQL语句,然后再根据对象标识符多次查询并实例化持久对象,
      因此该方法会导致典型的n+1查询语句的存在
      iterator方法是可以使用Hibernate二级缓存的,而list()方法则只能利用Session所在的一级缓存而无法利用二级缓存中的持久对象。
      在Hibernate中存在两种缓存,一种是可以由程序员进行控制的二级缓存,可以对二级缓存进行定制,另外一种是Hibernate内部的缓存,称为一级缓存,
      该缓存通过org.hibernate.engine.PersistenceContext进行管理,并在Session接口的实现类SessionImpl中进行定义
          public interface PersistenceContext {
            public void addEntity(EntityKey key, Object entity);
            public Object getEntity(EntityKey key);
            public boolean containsEntity(EntityKey key);
            public Object removeEntity(EntityKey key);
            public EntityEntry addEntity();
          }
      由此可见,为了避免出现这种情况,一个比较常见的做法就是对使用了二级缓存的持久对象第一次访问时使用list方法加载持久对象到缓存中,以及在修改
      持久对象时使用list方法,其他情况下使用iterate方法来充分利用二级缓存,避免了过多的SQL操作。
      注意:
         iterate()和list()方法在海量数据的查询都容易出现内存溢出的情况,通过iterate()方法并配合Hibernate缓存管理的接口,在海量数据查询中可以很好
      地解决内存问题,如
               while(it.hasNext()) {
                    Object object = (Object)it.next();
                    session.evict(object);    //remove this instance from the session cache
                    sessionFactory.evict(Object.class, object.getId());  //evict any entry from the second level cache
               }
              
      3:多对象查询
      多对象查询在Hibernate中被称为元组(tuples),即查询结果集的一条结果行中包含多个持久对象,此时查询的结果以属组的形式返回,其结果数组的顺序和查询
      HQL返回值顺序一致:
          Iterator kettensAndMothers = sess.createQuery(
            "select kitten, mother from Cat kitten join kitten.mother mother").list().iterator();
           
            while(kittenAndMothers.hasNext()) {
                Object[] tuple = (Object[]) kittenAndMothers.next();
                Cat kitten = tuple[0];
                Cat mother = tuple[1];
            }
            此处Cat对象通过join关联了mother属性的Cat对象,HQL取得一个对象数组,第一个元素代表Cat的kitten实例,第二个元素代表Cat的mother实例
           
       4:统计查询:通过在HQL查询的select语句中加入指定的类属性,SQL统计函数等,可以实现基本的统计查询功能。
          如:
             Iterator results = session.createQuery(
                              "select c.name, MIN(c.creationDate), count(c) from Company c group by c.name")
                              .list()
                              .iterator();
                          
             while(results.hasNext()) {
                 Object[] row = (Object[]) results.next();
                 String name = (String)row[0];
                 Date oldest = (Date)row[1];
                 Integer count = (Integer)row[2];
             }
            
             row[0] --> c.name
             row[1] --> MIN(c.creationDate)
             row[2] --> COUNT(c)
            
        5:绑定参数式查询
        使用PreparedStatement的JDBC代码如下:
           PreparedStatement ps = conn.prepareStatement("select c.name, c.url, c.creation_date from Company c where c.name=?");
           ps.setString(1, "taobao.com");
           ResultSet rs = ps.executeQuery();
         
        使用Hibernate的Query实现:
           Query query = session.createQuery("select c.name, c.url, c.creationDate from Company c where c.name=?");
           query.setString(0, "taobao.com");
           List list = q.list();
        在JDBC中参数是从1开始的,而Query则是从0开始的

原创粉丝点击