Hibernate的查询方式
 Hibernate总的来说共有三种查询方式:HQL、QBC和SQL三种。但是细分可以有如下几种:
一、HQL查询方式
   
这一种我最常用,也是最喜欢用的,因为它写起来灵活直观,而且与所熟悉的SQL的语法差不太多。条件查询、分页查询、连接查询、嵌套查询,写起来与SQL语法基本一致,唯一不同的就是把表名换成了类或者对象。其它的,包括一些查询函数(count(),sum()等)、查询条件的设定等,全都跟SQL语法一样。
###注意:
    
在hql中关键字不区分大小写,但是属性和类名区分大小写
示例1:
  static void query(String name){
  Session s=null;
  try{
  
s=HibernateUtil.getSession();
   //from后面是对象,不是表名
   String hql="from Admin as admin where
admin.aname=:name";//使用命名参数,推荐使用,易读。
   Query
query=s.createQuery(hql);
   query.setString("name",
name);
  
List<Admin>
list=query.list();
   for(Admin admin:list){
   
System.out.println(admin.getAname());
  }
  }finally{
   if(s!=null)
   s.close();
 }
}
######!!!!!!!!!!!!!对于多对一关系查询:
 String
hql = "from Student where Class.className = '二班'";
(Student实体类中含有Class对象的引用。这样相当于两张表的联合查询)
示例2(分页查询):
    Query query
= session.createQuery("from Customer c
order by c.name asc");
query.setFirstResult(0);
query.setMaxResults(10);
List result = query.list();
    说明:
   –setFirstResult(int firstResult):设定从哪一个对
象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0。默认情况下,Query和Criteria接口从查
询结果中的第一个对象,也就是索引位置为0的对象开始检索。 
   
–setMaxResult(int maxResults):设定一次最多检索出的对象数目。默认情况下,Query和Criteria接口检索出查询结果中所有的对象。
适用情况:常用方法,比较传统,类似jdbc。缺点:新的查询语言,适用面有限,仅适用于Hibernate框架。
二、QBC(Query By Criteria)
查询方式
   
这种方式比较面向对象方式,重点是有三个描述条件的对象:Restrictions,Order,Projections。使用QBC查询,一般需要以下三个步骤:
   1、 使用Session实例
的createCriteria()方法创建Criteria对象
  
2、使用工具类Restrictions的方法为Criteria对象设置查询条件,Order工具类的方法设置排序方式,Projections工具类的方法进行统计和分组。
   3、
使用Criteria对象的list()方法进行查询并返回结果
Restrictions类的常用方法:
Restrictions类的常用方法:
Order类的常用方法:
方法名称 | 
描述 | 
| Order.asc | 升序 | 
| Order.desc | 降序 | 
Projections类的常用方法
示例:static
void cri(String name,String password){
  Session s=null;
  try{
  
s=HibernateUtil.getSession();
   Criteria c=s.createCriteria(Admin.class);
  
c.add(Restrictions.eq("aname",name));//eq是等于,gt是大于,lt是小于,or是或
  
c.add(Restrictions.eq("apassword", password));
  
List<Admin>
list=c.list();
   for(Admin admin:list){
   
System.out.println(admin.getAname());
   }
  }finally{
   if(s!=null)
   s.close();
  }
}
示例2(分页查询):
    Criteria
criteria = session.createCriteria(Customer.class);
criteria.addOrder( Order.asc("name") ); //排序方式
criteria.setFirstResult(0);
criteria.setMaxResults(10);
List result = criteria.list()
 
适用情况:面向对象操作,革新了以前的数据库操作方式,易读。缺点:适用面较HQL有限。
三、QBE(Query By
Example)例子查询方式
   将一个对象的非空属性作为查询条件进行查询。
 示例:Session session =
SessionFactory.getCurrentSession();
  User user = new
User();
  
user.setName("ijse");
   Transaction ts =
session.beginTransaction();
    try {
       
Criteria criteria =
session.createCriteria(User.class);
       
criteria.add(Example.create(user));
     
user= (User)
criteria.list().get(0);   
      
session.commit();
   } catch (HibernateException
ex) {
      
ts.rollBack();
      
ex.printStackTrace();
   }
  
System.out.println(user.getName());
适用情况:面向对象操作。  
缺点:适用面较HQL有限,不推荐。
四、DetachedCriteria:离线条件查询
  
离线查询就是建立一个DetachedCriteria对象,将查询的条件等指定好,然后在session.beginTransaction()后将这个对象传入。通常这个对象可以在表示层建立,然后传入业务层进行查询。
  1、建立DetachedCriteria对象
    DetachedCriteria dc =
DetachedCriteria.forClass(User.class);
  int id = 1;
  if (id != 0)
   dc.add(Restrictions.eq("id", id));
  Date age = new Date();
  if (age != null)
   dc.add(Restrictions.le("birthday",
age));
  List users = dc(dc);//执行查询
  System.out.println("离线查询返回结果:" + users);
 2、执行查询
   static List
dc(DetachedCriteria dc) {
   Session s =
HibernateUtil.getSession();
  Criteria c =
dc.getExecutableCriteria(s);
  List rs = c.list();
  s.close();
  return rs;
}
适用情况:面向对象操作,分离业务与底层,不需要字段属性摄入到Dao实现层。 
缺点:适用面较HQL有限。
五、命名查询
  1、在数据映射元文件中进行配置如下:
 <?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>
   
<class name="com.sy.vo.User" table="user"
catalog="news">
   ....
   
</class>
   
<!-- 命名查询:定义查询条件 -->
    <query name="getUserById">
    
<![CDATA[from User where
id=:id]]>
   
</query>
   
<!-- 命名查询中使用sql,不推荐使用,影响跨数据库
    <sql-query
name="getUserById2">
    
<![CDATA[select * from User where
]]>
   
</sql-query>
-->
</hibernate-mapping>
  2、在java代码中写入:
  static List namedQuery(int id) {
  Session s = HibernateUtil.getSession();
  Query q =
s.getNamedQuery("getUserById");
  q.setInteger("id", id);
  return q.list();
 }
适用情况:万能方法,有点像ibatis轻量级框架的操作,方便维护。 
缺点:不面向对象。基于hql和sql,有一定缺陷。
六、SQL查询
   示例:
static List sql() {
 Session s = HibernateUtil.getSession();
  Query q =
s.createSQLQuery("select * from user").addEntity(User.class);
  List<User> rs =
q.list();
  s.close();
  return rs;
 }
适用情况:不熟悉HQL的朋友,又不打算转数据库平台的朋友,万能方法  
缺点:破坏跨平台,不易维护,不面向对象。
七、OID查询方式
   
按照对象的OID来检索对象。Session的get()和load()方法提供了这种功能。如果在应用程序中事先知道了OID,就可以使用这种检索对象的方式。 
八、Query.iterator的N+1查询(基于一的HQL,多见于一对多、多对多的关联映射)
  N +
1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题
  
所谓的N+1是在查询的时候发出了N+1条sql语句
   1: 首先发出一条查询对象id列表的sql
   N:
根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句
* list和iterate的区别?
   *
list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据
   *
iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题
  示例:Query
q=session.createQuery(“from UserInfo”);
    
Iterator<UserInfo>
list=q.iterate();
    
While(list.hasNext()) {
    
UserInfo st = (UserInfo)
it.next();
    
System.out.println(st.getName());
    }
避免N+1查询解决方法:
   
1、可以将fetch抓取数据的属性改为“join”,来避免N+1次的查询;
   
2、使用二级缓存
九、复查查询(基于二:QBC的深度查询)
 
复合查询就是在原有查询的基础上再进行查询,可以调用Criteria对象的createCriteria()方法在这个Criteria对象的基础上再进行查询。
示例:Session session = SessionFactory.getCurrentSession();
    User user =
new User();
    Transaction
ts = session.beginTransaction();
   
try  {
   Criteria criteria1 =
session.createCriteria(Room.class);
   Criteria 
criteria2 =criterial.createCriteria("User");
    
criteria2.add(Restrictions.eq("name",new
String("ijse"));
   user= (User)
criteria.list().get(0);
   
session.commit();
  } catch (HibernateException ex) {
   ts.rollBack();
  ex.printStackTrace();
 }
  System.out.println(user.getName());
                    
                
                
            
        
浙公网安备 33010602011771号