还支持数据库的类型转换函数,如cast(... as ...),第二个参数是Hibernate的类型名,或者extract(... from ...),前提是底层数据库支持ANSI cast()?和extract()。
例如:
cast(arg1 as arg2);arg1是要转换的数据,arg2是目标类型(不是数据库类型名,是hibernate类型名:比如目标类型是varchar,必须写string)
SELECT CAST( ’2012-12-24′ AS DATE ) 把字符串转换成date类型
SELECT CAST( 2012 AS string ) 把数字转化成字符串
SELECT CAST( ‘baiduzhidao’ AS char(3) ) 取指定长度的字符
在HQL中子查询一般出现在where子句中,不能像sql语句那样在from后嵌套子查询,通过子查询来查询某个字段等。如:
List list=session.createQuery(“from Customer c where 1>(select count(o) from c.orders o)”).list();
下面这种子查询是正确的:
Query query=em.createQuery("select g.ginID as ginID,(select x.name from Gstorage x where x.gstorageID=g.glocationID) as gstorageN from Gin g ");
下面这种子查询是错误的:
Query query=em.createQuery("select o.ginID as ginID from ( select g.ginID as ginID from Gin g ) o");
还可以在HQL语句中使用Java public static final 类型的常量,例如eg.Color.TABBY。
除此之外,where子句还支持如下的特殊关键字用法。
in与between...and可按如下方法使用:
from DomesticCat cat where cat.name between ‘A‘ and ‘B‘
from DomesticCat cat where cat.name in ( ‘Foo‘,‘Bar‘,‘Baz‘)
当然,也支持not in和not between...and的使用,例如:
from DomesticCat cat where cat.name not between ‘A‘ and ‘B‘
from DomesticCat cat where cat.name not in ( ‘Foo‘,‘Bar‘,‘Baz‘ )
子句is null与is not null可以被用来测试空值,例如:
from DomesticCat cat where cat.name is null;
from Person as p where p.address is not null;
size关键字用于返回一个集合的大小,例如:
from Cat cat where cat.kittens.size > 0
from Cat cat where size(cat.kittens) > 0
对于有序集合,还可使用minindex与maxindex函数代表最小与最大的索引序数。同理,可以使用minelement与maxelement函数代表集合中最小与最大的元素。例如:
from Calendar cal where maxelement(cal.holidays) > current date
from Order order where maxindex(order.items) > 100
from Order order where minelement(order.items) > 10000
where子句中,有序集合的元素(arrays, lists, maps)可以通过[ ]运算符访问。例如:
//items是有序集合属性,items[0]代表第一个元素
from Order order where order.items[0].id = 1234
//holidays是map集合属性,holidays[national day]代表其中一个元素
select person from Person person, Calendar calendar
where calendar.holidays[‘national day‘] = person.birthDay
and person.nationality.calendar = calendar
//下面同时使用list 集合和map集合属性
select item from Item item, Order order
where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11
select item from Item item, Order order
where order.items[ maxindex(order.items) ] = item and order.id = 11
在[]中的表达式甚至可以是一个算术表达式,例如:
select item from Item item, Order order
where order.items[ size(order.items) - 1 ] = item
连接查询
迫切左外连接
from User u left join fetch u.student s where u.name like ‘%java%‘
左外连接
左连接就是要把左边这个表里面的所有的数据显示出来。
from User u left join u.student s where u.name like ‘%java%‘
迫切内连接
from User u inner join fetch u.student where u.name like ‘%java%‘
内连接
内连接是把所有的相等的,完全符合条件的列出来。
内连(join).可以将inner 关键字省略,默认就是内连接。
from User u inner join u.student where u.name like ‘%java%‘
右外连接
from User u right join u.student where u.name like ‘%java%‘
order by子句
排序order by
HQL和SQL的使用方法很类似,"ASC"和"DESC"分别为升序和降序,如果不显式注明,HQL中默认为asc升序。
//先按照年龄降序排序,然后再按出生日期升序排序
Query query = sessionFactory.getCurrentSession().createQuery("select p from Person p order by p.age desc, p.birthday asc");
group by子句
分组查询,大部分标准的SQL聚集函数都可以在HQL语句中使用,比如:
count(),sum(),max(),min(),avg()等。
select cat.color, sum(cat.weight), count(cat) from Cat cat group by cat.color
Query query=sessionFactory.getCurrentSession().createQuery("select p.sex,count(*) from Person p group by p.sex");
HQL和可以使用和SQL那样的grouping,group by rollup(...)
如:
select g.belongOrganID,g.customerN,g.vtype,(case when grouping(g.belongOrganID)=0 then 1 when grouping(g.belongOrganID)=1 then 0 end )+(case when grouping(g.customerN)=0 then 1 when grouping(g.customerN)=1 then 0 end )+(case when grouping(g.vtype)=0 then 1
when grouping(g.vtype)=1 then 0 end ),uuid() as ID,count(*) as count, sum(g.totoalPrice) as totoalPrice from Gin o where 1=1 group by rollup(g.belongOrganID,g.customerN,g.vtype)
distinct
有时查询结果集中有相同的数据,关键词distinct用于返回唯一不同的数据。
select [distinct] object(variable) from abstractschemaname [as] variable [where value comparison value]
子查询
如果底层数据库支持子查询,则可以在HQL语句中使用子查询。与SQL中子查询相似的是,HQL中的子查询也需要使用()括起来。如:
from Cat as fatcat
where fatcat.weight > ( select avg(cat.weight) from DomesticCat cat )
如果select中包含多个属性,则应该使用元组构造符:
from Cat as cat
where not ( cat.name, cat.color ) in (
select cat.name, cat.color from DomesticCat cat
)
命名查询
命名查询也和EJB3 QL一样使用@NamedQuery注解。
@NamedQuery
我们可以使用@NamedQuery注释来定义命名查询,这个注释可以放在任何实体Bean的上方,但为了便于管理,最好放在相关的实体Bean上方。
@NamedQuery(name="MyQuery",query="select p from PersonFlight p where name like ?1")
@NamedQueries( {
@NamedQuery(name = "person.query", query = "from Person p where p.id=? "),
@NamedQuery(name = "person.query1", query = "from Person p where p.id=? ") })
也可以在hbm.xml文件中配置命名查询:
<query name="findGroupsByUser">
<![CDATA[
select distinct g
from org.jbpm.pvm.internal.identity.impl.MembershipImpl m
join m.user u
join m.group g
where u.id = :userId
]]>
</query>
Query query = session.getNamedQuery("findGroupsByUser");
query.setInteger("userId", 25);
List result= query.list();
Hibernate org.hibernate.Query类
setParameter()方法:
在Hibernate的HQL查询中可以通过setParameter()方法邦定任意类型的参数,如下代码:
String hql="from User user where user.name=:customername";//注意=:后不要有空格
Query query=session.createQuery(hql);
query.setParameter("customername",name,Hibernate.STRING);
如上面代码所示,setParameter()方法包含三个参数,分别是命名参数名称,命名参数实际值,以及命名参数映射类型。对于某些参数类型 setParameter()方法可
以更具参数值的Java类型,猜测出对应的映射类型,因此这时不需要显示写出映射类型,像上面的例子,可以直接这样写:
query.setParameter("customername",name); 但是对于一些类型就必须写明映射类型,比如java.util.Date类型,因为它会对应Hibernate的多种映射类型,比如
Hibernate.DATA或者Hibernate.TIMESTAMP。
setProperties()方法:
在Hibernate中可以使用setProperties()方法,将命名参数与一个对象的属性值绑定在一起,如下程序代码:
Customer customer=new Customer();
customer.setName("pansl");
customer.setAge(80);
Query query=session.createQuery("from Customer c where c.name=:name and c.age=:age");
query.setProperties(customer);
setProperties()方法会自动将customer对象实例的属性值匹配到命名参数上,但是要求命名参数名称必须要与实体对象相应的属性同名。
查询单个字段
String hql = " select name from Users";
Query query = session.createQuery(hql);
*********************
createSQLQuery(String str)
例如,Object obj=session.createSQLQuery("select o.name from organ o where o.id=1");
如果只查询一列并只有一个结果则返回Object,如果有多个结果则返回List<Object>。如果查询多列且有多个结果则返回List<Object[]>。
List<Object[]> listobj=session.createSQLQuery("select o.name,o.id from organ o");
******************
hql中+号的另一中作用:
createQuery("select new Vcolor(c.vcolorID,c.name) from Vconfig o,Vcolor c where o.vconfigID=:vconfigId and o.outterColor like ‘%‘+c.vcolorID+‘%‘ ");
表示从Vcolor中找出VcolorID在指定的Vconfig对象的outterColor属性中的vcolor对象。不能写成
like ‘%c.vcolorID%‘ 。这种写法其实和sql写法一样。
****************
case when:
1. select sum(case when otype=‘A‘ then price when otype=‘B‘ then -price end ) from Entity (sql中支持,但hql查询时,控制台查询语句缺少 ‘when otype=‘B‘ then -price ’,也就是只有otype=‘A‘ 的情况)
2.select sum(case when otype=‘A‘ then price else -price end ) from Entity (支持)
3. select sum(case when otype=‘A‘ then price else case when otype=‘B‘ then -price end end ) from Entity (支持)
*********************
inner join(内连接)
left outer join(左外连接)
right outer join(右外连接)
full join (全连接,并不常用)
HQL中的条件用with即:left join ... with...
SQL中的条件用on即:left join ... on...
语句inner join, left outer join 以及 right outer join 可以简写。
from Cat as cat join cat.mate as mate left join cat.kittens as kitten
通过HQL的with关键字,你可以提供额外的join条件。
from Cat as cat left join cat.kittens as kitten with kitten.bodyWeight > 10.0
还有,一个"fetch"连接允许仅仅使用一个选择语句就将相关联的对象或一组值的集合随着他们的父对象的初始化而被初始化,这种方法在使用到集合的情况下尤其有用,对于关联和集合来说,它有效的代替了映射文件中的外联接 与延迟声明(lazy declarations).
from Cat as cat inner join fetch cat.mate left join fetch cat.kittens
一个fetch连接通常不需要被指定别名, 因为相关联的对象不应当被用在 where 子句 (或其它任何子句)中。同时,相关联的对象 并不在查询的结果中直接返回,但可以通过他们的父对象来访问到他们。
from Cat as cat inner join fetch cat.mate left join fetch cat.kittens child left join fetch child.kittens
如果你使用属性级别的延迟获取(lazy fetching)(这是通过重新编写字节码实现的),可以使用 fetch all properties 来强制Hibernate立即取得那些原本需要延迟加载的属性(在第一个查询中)。
from Document fetch all properties order by name
from Document doc fetch all properties where lower(doc.name) like ‘%cats%‘
例如:
public SureOrder getSureOrderVO(Integer productId) {
String hql = "select pd.id as prodid,pd.cuxiaoPrice as cuxiaoPrice,pd.types as types,pd.price as price,pd.newprice as newprice,p.nodeId,p.imgurl as imgurl,p.types as types,p.factId as factId,p.qianYueId as qianyueId,p.guiGe as guiGe,p.name as name,p.pinPai
as pinPai from Product pd,Prod p where p.id=pd.prodId and pd.id =?";
Query query = productDao.getProductDetail(productId,hql);
//主要起作用的就是下面的这个方法:SureOrder是我要封装的VO类.这样hibernate在执行hql查询的时候,会直接将结果封装为SureOrder对象.
List list = query.setResultTransformer(Transformers.aliasToBean(SureOrder.class)).list();
if(!list.isEmpty()){
return (SureOrder) list.get(0);
}
return null;
}
**************************
select中的new map前面也可以使用distinct :
select distinct new map(...)