Hibernate Query Language HQL
HQL提供了更加丰富灵活的特性,它在涵盖了Criteria功能范围的前提下,提供了更加强大的查询能力。
1、实体查询
String hql = "from TPerson tp where tp.age=20";
List list = session.createQuery(hql).list;
取出age=20的所有TPerson对应记录。也可以在HQL中采用全路径类名,特别是在应用中存在同名类(包名不同)的情况下,如:
hql = " from com.person.pojo.TPerson tp where tp.age = 20";
注意,在Hibernate中,查询的实体目标存在着继承关系发判断,如"from TPerson"将返回所有Tperson以及TPerson子类的记录。
"like 'Liu%'"表示以Liu开头的字符串,"like '%Liu'"表示以Liu结尾的字符串,"like '%Liu%'"表示包含Liu的字符串。
2、属性查询
有时并不需要获取完整的实体对象,需要的可能仅仅是实体对象的某个属性:
List list = session.createQuery("select tp.name,tp.age from TPerson tp").list();
此时,list数据结构中,每个条目都是一个对象数组(Object[]),其中依次包含了所获取的属性数据。这种返回数组的方式不够符合
面向对象的风格,可通过在HQL中构造动态对象实例的方法对这些平面化的数据进行封装:
List list = session.createQuery("select new TPerson(tp.name,tp.age) from TPerson tp").list();
注意:在TPerson类中要存在TPerson(String name,Integer age)的构造方法。
利用distinct关键字,剔除返回集中的重复记录:
List list = session.createQuery("select distinct tp.name,tp.age from TPerson tp").list();
3、实体更新与删除
Transaction tran = session.beginTransaction();
String hql = "update TPerson set age = 14 where id = 22";//更新
//String hql = "delete TPerson where id = 34";//删除
query=session.createQuery(hql);
int leavel = query.executeUpdate();//返回的是update/delete的条数
System.out.println(leavel);
tran.commit();
4、分组(Group By)与排序(Order By)
String hql="select count(*),tp.age from TPerson tp group by tp.age having count(*)>2 order by tp.age desc";
按照年龄分组,统计显示各年龄段的人数大于2的数据,并根据年龄降序排列。
5、参数绑定
顺序占位符 "?"
String hql = " from TPerson tp where tp.name like ? and tp.age > ?";
Query query=session.createQuery(hql);
query.setString(0, "Fang%");
query.setInteger(1, 20);
List list query.list();
引用占位符 ":name"
String hql = " from TPerson tp where tp.name like :name and tp.age > :age";
Query query=session.createQuery(hql);
query.setParameter("name", "Fang%");
query.setParameter("age", new Integer(20));
List list = query.list();
也可以用JavaBean封装查询参数,如:
class TPersonQuery{
private String name;
private Integer age;
// getter/setter
}
查询代码:
String hql = " from TPerson tp where tp.name like :name and tp.age > :age";
Query query=session.createQuery(hql);
TPersonQuery tpq = new TPersonQuery();
tpq.setName("Fang%");
tpq.setAge(new Integer(20));
query.setProperties(tpq);
List list = query.list();
参数绑定机制可以使得查询语法与具体参数数值相互独立,杜绝了参数值对查询语法本身的影响。
7、引用查询
可以采用将SQL配置化的方式,将SQL保存在配置文件中,需要调用的时候再进行读取。Hibernate提供了HQL可配置化的内置支持。
<ibernate-mapping>
<class name="com.person.pojo.TPerson" table="t_user" batch-size="5">
......
</class>
<query name="queryByname">
<![cdata[from TPerson tp where tp.name=:name]]>
</query>
</hibernate-mapping>
然后通过Session.getNamedQuery方法从配置文件中调用对应的HQL,如:
Query query = session.getNamedQuery("queryByname");
query.setParameter("name", "Fang%");
List list = query.list();
8、联合查询
HQL提供了以下几种联合查询机制:
inner join;left outer join;right outer join;full join
a、inner join
hql="from TPerson tp inner join fetch tp.address";
inner join 返回所有满足关联条件的记录组合,对应的sql语句是:
sql="select * from t_person tp inner join t_address addr on tp.id=addr.person_id";
注意:“inner join fetch ”中的fetch关键字表明TAddress对象读出后立即填充到对应的TPerson对象(address属性)中。如果忽略该关键字,则得到的结果集中,每个条目都是一个Object数组,包括了一个TPerson对象及其对应的TAddress对象。
b、left outer join
hql="from TPerson tp left join fetch tp.address";
返回的结果集中,包含了t_person表(HQL中位于左侧的表)中的所有记录,及其对应的地址信息,如无则以NULL代替。
sql="select * from t_person tp left outer join t_address addr on tp.id=addr.person_id";
c、right outer join
hql="from TPerson tp right join tp.address";
与left outer join相反,right outer join 返回的是t_address(HQl中位于右侧的表)中的所有记录及其对应的t_person记录,如无则以NULL代替。
注意:fetch关键字只对inner join和left outer join有效。对tight outer join 而言,由于作为关联对象容器的t_person对象可能为null,所以也就无法通过关键字fetch强制Hibernate进行集合填充操作。意味着只能通过对返回集合中的各个对象数组进行处理,获取所需数据。
d、full join
hql="from TPerson tp full join tp.address";
返回两张表记录的笛卡尔交集。它是left outer join 和 right outer join的并集。
7、子查询
hql="from Tperson tp where (select count(*) from tp.address)>1";
sql="select ...... from t_person tp where ((select count(*) from t_address addr where tp.id=addr.person_id)>1)";
HQL中,子查询必须出现在where子句中,且必须以一对圆括号包围。