HQL有关查询详解

hibernate 查询

hibernate 2010-11-20 09:45:36 阅读80 评论0  字号: 订阅

HQLHibernate Qusery Language,如果你已经熟悉它,就会发现它跟SQL非常相像。不过 你不要被表面的假象迷惑,HQL是面向对象的(OO,用生命的眼光看待每一个对象,他们是如此 鲜活)。如果你对JAVASQL语句有一定了解的话,那么HQL对你简直易如反掌,你完全可以利用在公车上的时间掌握它。

以下从几个方面进行慢慢深入:

1。大小些敏感

大家知道SQL-92 Query是对大小写不敏感的,但是在HQL(前面提到它是OO的)中对对象类的名称和属性确实大小写敏感的(符合java编程语法)。

HQL 子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分

如:sElect cat.name from Cat as catselect cat.name from Cat as cat是一样的

但是:

sElect cat.name from CAT as catselect cat.name from Cat as cat确实不一样的。

2from语句

最简单的:

from eg.Cat

它只是简单的返回所有eg.Cat的实例,通常我们此时会为eg.Cat其个别名,因为在query的其余部分可能会用到(参看上边关于大小写敏感时的例子情形),如:

from eg.Cat as cat 这里as可以省略。

上边只是单表查询,多表的情况如下写法:

from eg.Cat, eg.Dog

from eg.Cat as cat, eg.Dog as dog

3join相关

(inner) join

left (outer) join

right (outer) join

full join

HQL同样对SQL中的这些特性支持

下面插播一个小话题,关于上边的那些特性,我一直都没怎么用,今天既然说到这里,就想把上边的几个特性的用法说一下,也算对自己的一个补充:

假设有两个表:部门、员工,下面列举一些数据:

员工(Employee)

  ID     Name    DepNo

  001   Jplateau    01

  002    Jony        01

  003   Camel      02

部门(Department)

  ID   Name

  01   研发部

  02   营销部

Hibernate中我们操纵的都是对象,所以我们操纵的是部门类和员工

1).(inner) join

select employee.ID as id1,employee.Name as name1,

department.ID as id2,department.Name as name2  from Employee as employee

 join  Department as department on employee.DepNo=department.ID (注意到条件语句我用on 没有用where)

那么执行结果是什么呢?

id1 name1 id2 name2

++++++++++++++++++++++++++++++++++++++

001 Jplateau 01 研发部

002 Jony 01 研发部

2).left (outer) join

select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name

as name2 from Employee as employee left join Department as department on employee.DepNo=

department.ID

那么执行结果又该是什么呢?

id1 name1 id2 name2

++++++++++++++++++++++++++++++++++++++

001 Jplateau 01 研发部

002 Jony 01 研发部

003 Camel null null

{就是说此时我要已第一个表的记录多少为准,第二个表中没有相应纪录的时候填充null}

3). right (outer) join

select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name

as name2 from Employee as employee right join Department as department on employee.DepNo=

department.ID

那么执行结果又该是什么呢?

id1 name1 id2 name2

++++++++++++++++++++++++++++++++++++++

001 Jplateau 01 研发部

002 Jony 01 研发部

null null 02 营销部

{就是说此时我要已第二个表的记录多少为准,第一个表中没有相应纪录的时候填充null}

4select语句

就是要确定你要从查询中返回哪些对象或者哪些对象的属性。写几个例子吧:

select employee form Employee as employee

select employee form Employee as employee where employee.Name like 'J%'

select employee.Name form Employee as employee where employee.Name like 'J%'

select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name

as name2 from Employee as employee right join Department as department on employee.DepNo=

department.ID

select elements(employee.Name) from Employee as employee

(不明白elements到底是做什么用的?望给于说明)

等等

5。数学函数

JDO目前好像还不支持此类特性。

avg(...), sum(...), min(...), max(...)

count(*)

count(...), count(distinct ...), count(all...)

其用法和SQL基本相同

select distinct employee.name from Employee as employee

select count(distinct employee.name),count(employee) from Employee as employee

6polymorphism (暂时不知道如何解释?)

from com.test.Animal as animal

不光得到所有Animal得实例,而且可以得到所有Animal的子类(如果我们定义了一个子类Cat

一个比较极端的例子

from java.lang.Object as o

可以得到所有持久类的实例

7where语句

定义查询语句的条件,举几个例子吧:

from Employee as employee where employee.Name='Jplateau'

from Employee as employee where employee.Name like 'J%'

from Employee as employee where employee.Name like '%u'

where语句中“=”不光可以比较对象的属性,也可以比较对象,如:

select animal from com.test.Animal as animal where animal.name=dog

8。表达式

SQL语句中大部分的表达式在HQL中都可以使用:

mathematical operators +, -, *, /

binary comparison operators =, >=, <=, <>, !=, like

logical operations and, or, not

string concatenation ||

SQL scalar functions like upper() and lower()

Parentheses ( ) indicate grouping

in, between, is null

JDBC IN parameters ?

named parameters :name, :start_date, :x1 (这种应该是另一种"?"的变通解决方法)

SQL literals 'foo', 69, '1970-01-01 10:00:01.0'

Java public static final constants eg.Color.TABBY

其他不必解释了,在这里我只想对查询中的参数问题说明一下:

大家知道在SQL中进行传递参数进行查询的时候,我们通常用PreparedStatement,在语句中写一大堆的

hql中也可以用这种方法,如:

List mates = sess.find(

"select employee.name from Employee as employee " +

"where employee.Name=? ",

name,

Hibernate.STRING

);

(说明:上面利用Session里的find方法,在hibernateapi Session中重载了很多find方法,它可以满足你多种形式的查询)

上边是一个参数的情形,这种情况下紧接着引入参数和定义参数的类型,当为多个参数,调用另一个find方法,它的后两个

参数都是数组的形式。

还有另外一种方法来解决上边的问题,JDO也有这样的方法,不过和hibernate的表现形式上有差别,但他们两个骨子里却是

一样的,如:

Query q = sess.createQuery("select employee.name from Employee as employee where employee.Name=:name");

q.setString("name", "Jplateau");

//当有多个参数的时候在此逐一定义

Iterator employees = q.iterate();

9order 语句

sql语句没什么差别,如:

select employee.name from Employee as employee where employee.Name like 'J%' order by employee.ID desc (或者asc)

10group by 语句

同样和sql语句没什么差别,如:

select employee.name,employee.DepNo from Employee as employee group by employee.DepNo

select foo.id, avg( elements(foo.names) ), max( indices(foo.names) ) from eg.Foo foo group by foo.id

{Note: You may use the elements and indices constructs inside a select clause, even on databases with no subselects.}

谁帮我解释一下上边两句,谢过!

11。子查询

hibernate同样支持子查询,写几个例子:

from eg.Cat as fatcat where fatcat.weight > ( select avg(cat.weight) from eg.DomesticCat cat )

(二)条件查询Criteria  Query。数学函数

JDO目前好像还不支持此类特性。

avg(...), sum(...), min(...), max(...)

count(*)

count(...), count(distinct ...), count(all...)

其用法和SQL基本相同

select distinct employee.name from Employee as employee

select count(distinct employee.name),count(employee) from Employee as employee

6polymorphism (暂时不知道如何解释?)

from com.test.Animal as animal

不光得到所有Animal得实例,而且可以得到所有Animal的子类(如果我们定义了一个子类Cat

一个比较极端的例子

from java.lang.Object as o

可以得到所有持久类的实例

7where语句

定义查询语句的条件,举几个例子吧:

from Employee as employee where employee.Name='Jplateau'

from Employee as employee where employee.Name like 'J%'

from Employee as employee where employee.Name like '%u'

where语句中“=”不光可以比较对象的属性,也可以比较对象,如:

select animal from com.test.Animal as animal where animal.name=dog

8。表达式

SQL语句中大部分的表达式在HQL中都可以使用:

mathematical operators +, -, *, /

binary comparison operators =, >=, <=, <>, !=, like

logical operations and, or, not

string concatenation ||

SQL scalar functions like upper() and lower()

Parentheses ( ) indicate grouping

in, between, is null

JDBC IN parameters ?

named parameters :name, :start_date, :x1 (这种应该是另一种"?"的变通解决方法)

SQL literals 'foo', 69, '1970-01-01 10:00:01.0'

Java public static final constants eg.Color.TABBY

其他不必解释了,在这里我只想对查询中的参数问题说明一下:

大家知道在SQL中进行传递参数进行查询的时候,我们通常用PreparedStatement,在语句中写一大堆的

hql中也可以用这种方法,如:

List mates = sess.find(

"select employee.name from Employee as employee " +

"where employee.Name=? ",

name,

Hibernate.STRING

);

(说明:上面利用Session里的find方法,在hibernateapi Session中重载了很多find方法,它可以满足你多种形式的查询)

上边是一个参数的情形,这种情况下紧接着引入参数和定义参数的类型,当为多个参数,调用另一个find方法,它的后两个

参数都是数组的形式。

还有另外一种方法来解决上边的问题,JDO也有这样的方法,不过和hibernate的表现形式上有差别,但他们两个骨子里却是

一样的,如:

Query q = sess.createQuery("select employee.name from Employee as employee where employee.Name=:name");

q.setString("name", "Jplateau");

//当有多个参数的时候在此逐一定义

Iterator employees = q.iterate();

9order 语句

sql语句没什么差别,如:

select employee.name from Employee as employee where employee.Name like 'J%' order by employee.ID desc (或者asc)

10group by 语句

同样和sql语句没什么差别,如:

select employee.name,employee.DepNo from Employee as employee group by employee.DepNo

select foo.id, avg( elements(foo.names) ), max( indices(foo.names) ) from eg.Foo foo group by foo.id

{Note: You may use the elements and indices constructs inside a select clause, even on databases with no subselects.}

谁帮我解释一下上边两句,谢过!

11。子查询

hibernate同样支持子查询,写几个例子:

from eg.Cat as fatcat where fatcat.weight > ( select avg(cat.weight) from eg.DomesticCat cat )

(二)条件查询Criteria  Query

 Criteria criteria = osession.createCriteria(Owner.class);

   criteria.add(Expression.eq("age", new Integer(100)));

   criteria.setFirstResult(2);                   //从返回结果的第二条记录开始的5条记录

   criteria.setMaxResults(5);

   List lc=criteria.list();

   System.out.println("条件查询");

   System.out.println(lc.size());

(三)原生SQL语句查询

1: QBE (Query By Example) 
   Criteria cri = session.createCriteria(Student.class);
 
   cri.add(Example.create(s)); //s
是一个 Student 对象 
   list cri.list();   
 
  
实质:创建一个模版,比如我有一个表serial 有一个  giftortoy 字段,我设置 serial.setgifttoy(/"2/"), 
        
则这个表中的所有的giftortoy 2 的数据都会出来 
QBC
查询方式 

QBC(Query By Criteria)
查询方式是 Hibernate 提供的更加面向对象的一种检索方式。 QBC 在条件查询上比 HQL 查询更为灵活,而且支持运行时动态生成查询语句。 
Hibernate 应用中使用 QBC 查询通常经过 3 个步骤 
  (1)
使用 Session 实例的 createCriteria() 方法创建 Criteria 对象 
  (2)
使用工具类 Restrictions 的相关方法为 Criteria 对象设置查询对象 
  (3)
使用 Criteria 对象的 list() 方法执行查询,返回查询结果 
Restrictions
类的常用方法 
Restrictions.eq(String propertyName,Object value)
 
等于 
Restrictions.allEq(Map propertyNameValues)
 
使用Map key/value 进行多个等于的比对 
Restrictions.gt(String propertyName, Object value)
 
大于 >    (gt----->greater than) 
Restrictions.ge(String propertyName, Object value)
 
大于等于 >=    (ge----->greater equal) 
Restrictions.It(String propertyName, Object value)
 
小于< (It---->less than) 
Restrictions.Le(String propertyName, Object value)
 
小于等于<= (le---->less equal) 
Restrictions.between(String propertyName, Object lo, Object hi)
 
对应SQL 语句的 Between 子句 
Restrictions.like(String propertyName, Object value)
 
对应SQL 语句的 LIKE 子句 
Restrictions.in(String propertyName, Collection value)
 
对应SQL 语句的 in 子句 
Restrictions.and(Criterion lhs, Criterion rhs)
 
And
关系 
Restrictions.or(Criterion lhs, Criterion rhs)
 
Or
关系 
Restrictions.sqlRestriction(String sql,Object[] values,Type[] types)
 
SQL
限定查询 

          
工具类Order 提供设置排序方式 
Order.asc(String propertyName)
 
升序排序 
Order.desc(String propertyName)
 
降序排序 

         
工具类Projections 提供对查询结果进行统计与分组操作 
Porjections.avg(String propertyName)
 
求某属性的平均值 
Projections.count(String propertyName)
 
统计某属性的数量 
Projections.countDistinct(String propertyName)
 
统计某属性的不同值的数量 
Projections.groupProperty(String propertyName)
 
指定一组属性值 
Projections.max(String propertyName)
 
某属性的最大值 
Projections.min(String propertyName)
 
某属性的最小值 
Projections.projectionList()
 
创建一个新的projectionList 对象 
Projections.rowCount()
 
查询结果集中记录的条数 
Projections.sum(String propertyName)
 
返回某属性值的合计 

QBE
查询 

   QBE
查询就是检索与指定样本对象具有相同属性值的对象。因此 QBE 查询的关键就是样本对象的创建,样本对象中的所有非空属性均将作为查询条件。 QBE 查询的功能子集,虽然 QBE 没有 QBC 功能大,但是有些场合 QBE 使用起来更为方便。 

        
工具类Example Criteria 对象指定样本对象作为查询条件 
Java
代码   
1  Session session = HibernateSessionFactory.getSessionFactory().openSession();  
 
2  Transaction ts = session.beginTransaction();  
 
3  Customer c =  new  Customer();  
 
4  c.setCname("Hibernate");  
 
5  Criteria criteria = session.createCriteria(Customer. class );  
 
6  Criteria.add(Example.create(c));  
 
7  Iterator it = criteria.list().iterator();  
 
8  ts.commit(); 
 
9  HibernateSessionFactory.closeSession(); 
 
QBC
分页查询 
   Criteria
为我们提供了两个有用的方法: setFirstResult(int firstResult) setMaxResults(int maxResults). 
setFirstResult(int firstResult)
方法用于指定从哪一个对象开始检索(序号从 0 开始),默认为第一个对象(序号为 0 ); setMaxResults(int maxResults) 方法用于指定一次最多检索出的对象数目,默认为所有对象。 
Java
代码   
1  Session session = HibernateSessionFactory.getSessionFactory().openSession();  
 
2  Transaction ts =  null ;  
 
3  Criteria criteria = session.createCriteria(Order. class );  
 
4  int  pageSize = 15;  
 
5  int  pageNo = 1;  
 
6  criteria.setFirstResult((pageNo-1)*pageSize);  
 
7  criteria.setMaxResults(pageSize);  
 
8  Iterator it = criteria.list().iterator();  
 
9  ts.commit();  
 
10  HibernateSessionFactory.closeSession();
 

QBC
复合查询 
  
复合查询就是在原有的查询基础上再进行查询。例如在顾客对定单的一对多关系中,在查询出所有的顾客对象后,希望在查询定单中money 大于 1000 的定单对象 
DetachedCriteria  criteria= DetachedCriteria . forClass (Model. class );
 
criteria.add(Restrictions. eq ( "userid" , userid));
 
criteria.add(Restrictions. eq ( "state" , false ));
 
criteria.add(Restrictions. not ( Expression . eq ( "freeze" , false )  ));
 
criteria.addOrder( Order. desc ( "createtime" ) );
 
return   modelDAO .findByCriteria(criteria);
 
Java
代码 
1  Session session = HibernateSessionFactory.getSessionFactory().openSession();  
 
2  Transaction ts = session.beginTransaction();  
 
3  Criteria cuscriteria = session.createCriteria(Customer. class );  
 
4  Criteria ordCriteria = cusCriteria.createCriteria("orders");  
 
5  ordCriteria.add(Restrictions.gt("money",  new  Double(1000)));  
 
6  Iterator it = cusCriteria.list().iterator();  
 
7  ts.commit();  
 
8  HibernateSessionFactory.closeSession(); 
 
QBC
离线查询 
  
离线查询又叫DetachedCriteria 查询,它可以在 Session 之外进行构造,只有在需要执行查询时才与 Session 绑定。 
2: QBC (Query By Criteria)
主要有 Criteria,Criterion,Oder,Restrictions 类组成 
   session = this.getSession();
 
   Criteria cri = session.createCriteria(JdItemSerialnumber.class);
 
   Criterion cron = Restrictions.like(/"customer/",name);
 
   cri.add(cron);
 
   list = cri.list();
 
   ==============================
 
  
比较运算符 
   HQL
运算符                    QBC 运算符                      含义 
      =                     Restrictions.eq()                 
等于 
      <>                   Restrictions.not(Exprission.eq()) 
不等于 
      >                     Restrictions.gt()                 
大于 
      >=                   Restrictions.ge()                 
大于等于 
      <                     Restrictions.lt()                 
小于  [Page] 
      <=                   Restrictions.le()                 
小于等于 
      is null             Restrictions.isnull()             
等于空值 
      is not null      Restrictions.isNotNull()          
非空值 
      like                 Restrictions.like()               
字符串模式匹配 
      and                Restrictions.and()                
逻辑与 
      and                Restrictions.conjunction()        
逻辑与 
      or                   Restrictions.or()                 
逻辑或 
      or                   Restrictions.disjunction()        
逻辑或 
      not                  Restrictions.not()                
逻辑非 
      in(
列表 )          Restrictions.in()                   等于列表中的某一个值  [Page] 
ont in(
列表 )         Restrictions.not(Restrictions.in()) 不等于列表中任意一个值 
      between x and y      Restrictions.between()            
闭区间 xy 中的任意值 
      not between x and y  Restrictions.not(Restrictions..between())
小于值 X 或者大于值 y 
3: HQL
 
   String hql = /"select s.name ,avg(s.age) from Student s group by s.name/";
 
   Query query = session.createQuery(hql);
 
   list = query.list();
 
   ....
 
4:
本地 SQL 查询 
   session = sessionFactory.openSession();
 
   tran = session.beginTransaction();
 
   SQLQuery sq = session.createSQLQuery(sql);
 
   sq.addEntity(Student.class);
 
   list = sq.list();
 
   tran.commit();
 
5: QID 
 
   Session
get() load() 方法提供了根据对象 ID 来检索对象的方式。该方式被用于事先知道了要检索对象 ID 的情况。  
Hibernate
HQL/QBC 查询语言比较的用法 
Hib
的检索方式  1 、导航对象图检索方式。通过已经加载的对象,调用 .iterator() 方法可以得到 order 对象如果是首次执行此方法, Hib 会从数据库加载关联的 order 对象,否则就从缓存中得到。  2 OID 检索方式。通过 session get load 方法知道了 OID 的情况下可以使用  3 HQL 检索方 

Hib
的检索方式 
   1
、导航对象图检索方式。通过已经加载的对象,调用 .iterator() 方法可以得到 order 对象如果是首次执行此方法, Hib 会从数据库加载关联的 order 对象,否则就从缓存中得到。 
2
OID 检索方式。通过 session get load 方法知道了 OID 的情况下可以使用 
3
HQL 检索方式。使用面向对象的 HQL 查询语句 session find 方法利用 HQL 来查询 
4
QBC 检索方式。利用 QBCAPI 来检索它是封装了基于字符串的查询语句 
5
、本地的 SQL 检索方式。使用本地数据库的 SQL 查询语句 Hib 会负责把检索到的 JDBC 结果集映射为持久化对象图。 
 
五种检索方式的使用场合和特点: 
HQL
: 是面向对象的查询语言,同 SQL 有些相似是 Hib 中最常用的方式。 
查询设定各种查询条件。 
支持投影查询,检索出对象的部分属性。 
支持分页查询,允许使用having group by 
提供内制的聚集函数,sum() min() max() 
能调用用户的自定义SQL 
支持子查询,嵌入式查询 
支持动态绑定参数 
建议使用Query 接口替换 session find 方法。 

Query Q = session.createQuery("from customer as c where c.name = :customerName" +"and c.age = :customerAge");
 
query.setString("customerName" , "tom");
 
   query.setInteger("customerAge" , "21");
 
   list result = query.list();
 
QBC : QBCAPI
提供了另一种方式,主要是 Criteria 接口、 Criterion 接口和 Expression  
Criteria criteria = session.createCriteria(customer.class);
 
   Criterion criterion1 =Expression.like("name","t%");
 
   Criterion criterion2 =Expression.eq("age",new Integer(21));
 
   Critera = criteria.add(criterion1) ;
 
   Critera = criteria.add(criterion2) ;
 
   list result = criteria.list();
 
或是: list result = session.createCriteria(Customer.class).add(Expression.eq("this.name","tom")).list(); 
SQL :
采用 HQL QBC 检索时, Hib 生成 SQL 语句适用所有数据库。 
Query query  =session.createSQLQuery("select {c.*} from customers c where c.name like : customername " + "and c.age =:customerage","c",customer.calss);
 
   query.setString("customername","tom");
 
   query.setInteger("customerage","21");
 
   list result = query.list();
 
/
多态查询 
   HQL
session.createQuery("from employee"); 
   QBC
session.createCriteria(employee.class); 
   HQL : session.createQuery("from hourlyEmployee");
 
   QBC : session.createCriteria(hourlyEmployee.class);
 
下面的HQL 查询语句将检索出所有的持久化对象: 
from java.lang.Object ;
 
from java.io.serializable ;
 
查询的排序 
1
、查询结果按照客户姓名升序排列: 
HQL
 
Query query = session.createQuery
 
("from customer c order by c.name");
 
QBC
 
Criteria criteria = session.createCriteria(customer.class);
 
criteria.addOrder(order.asc("name"));
 
HQL :
 
Query query = session.createQuery("from customer c orderby c.name asc , c.age desc");
 
QBC :
 
Criteria criteria =session.createCriteria(customer.class);
 
criteria.addOrder(order.asc ("name"));
 
criteria.addOrder(order.desc("age"));
 
import net.sf.hibernate.pression.Order
 
import mypack.Order
 
...........
 
Criteria criteria = session.createCritria (mypack.Order.class);
 
criteria.addOrder(net.sf.hibernate.Order.asc("name"));
 
///HQL
语句的参数绑定 Query 接口 
提供了绑定各种Hib 映射类型的方法。 
setBinary()
 
setString()
 
setBoolean()
 
setByte()
 
setCalendar()
 
setCharacter()
 
setDate()
 
setDouble()
 
setText()
 
setTime()
 
setTimestamp()
 
setEntity()
 
//
把参数与一个持久化类的事例绑定 
lsit result = session.createQuery
 
("from order o where o.customer = :customer").setEntity("customer" , customer).list ;
 
setParameter()
 
//
绑定任意类型的参数 
setProperties()
 
//
把命名参数与一个对象的属性值绑定 
Query query = session.createQuery
 
("from customer c where c.name =:name " + "and c.age =:age" );
 
Query.setProperties(customer);

Java代码  复制代码

1.    public AlBasic queryAlBasicByEtpsIdAndAnnlYear(String entityName, String etpsId, String annlYear) {   

2.            if (etpsId == null || "".equals(etpsId) || annlYear == null || "".equals(annlYear))   

3.                return null;   

4.            DetachedCriteria dc = DetachedCriteria.forEntityName(entityName);   

5.            dc.add(Restrictions.eq("etpsId", etpsId));   

6.            dc.add(Restrictions.eq("annlYear", annlYear));   

7.      

8.            List result = findByCriteria(dc);   

9.            if (result == null || result.size() == 0) {   

10.              return null;   

11.          }   

12.          return (AlBasic) result.get(0);   

13.      }  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值