Hibernate Query Language(HQL)
Criteria Query
Native SQL
下面对其分别进行解释
Hibernate Query Language:
HQL提供了是十分强大的功能它是针对持久化对象用取得对象而不进行updatedelete和insert等操作而且HQL是面向对象的具备继承多态和关联等特性
from子句
from子句是最简单的HQL例如from Student也可以写成 select s from Student s它简单的返回Student类的所有实例
值得注意的是除了JAVA类和属性的名称外HQL语句对大小写不敏感
select子句
有时并不需要取得对象的所有属性这时可以使用select子句进行属性查询如select sname from Student s
例 public void HQLselectDEMO()
{
TRegister user = new TRegister();
Session session = HibernateUtilcurrentSession();
Query query = sessioncreateQuery(select uuserName from TRegister u);
List list = querylist();
for(int i = ; i < listsize(); i++)
{
String name = (String)listget(i);
Systemoutprintln(name);
}
}如果要查询两个以上的属性桧以数组的方式返回如下 public void HQLselectDEMO()
{
TRegister user = new TRegister();
Session session = HibernateUtilcurrentSession();
Query query = sessioncreateQuery(select uuserName usex from TRegister u);
List list = querylist();
for(int i = ; i < listsize(); i++)
{
Object obj[] = (Object[])listget(i);
Systemoutprintln(obj[]+ 的性别是+obj[]);
}
}
在使用属性查询时由于使用对象数组操作和理解不太方便如果将 一个object[]中所有成员封装成一个对象就方便多了下面的程序做了示例 public void HQLselectDEMO()
{
Session session = HibernateUtilcurrentSession();
Query query = sessioncreateQuery(select new TRegister(uuserNameusex) from TRegister u);
List list = querylist();
for(int i = ; i < listsize(); i++)
{
//Object obj[] = (Object[])listget(i);
TRegister user = (TRegister)listget(i);
Systemoutprintln(usergetUserName()+ 的性别是+usergetSex());
}
/** *//**要正确运行以上程序需要在TRegister类中加入一个相应的构造函数
public TRegister(String userNameString sex) {
thisuserName = userName;
thissex = sex;
}
*/
}
统计函数查询
可以在HQL中使用函数经常使用的函数如下
count()统计记录条数
min()求最小值
max()求最大值
sum()求和
avg()求平均值
例如要取得Student实例的数量可以编写如下HQL语句
select count(*) from Student
取得Student平均年龄的HQL语句
select avg(sage) from Student as s
可以使用distinct去除重复的数据
select distinct sage from Student as s
where子句
HQL也支持子查询它通过where子句实现这一机制where子句可以让用户缩小要返回的实例的列表范围例如下面语句会返回所有名字为Bill的Student实例
Query query = sessioncreateQuery(from Student as s where sname=Bill);
where子句允许出现的表达式包括了SQL中可以使用的大多数情况
数学操作+*/
真假比较操作= >= <= <> != like
逻辑操作and or not
字符串连接||
SQL标题函数 如upper()和lower()
如果查询返回多条记录可以用以下关键字来量化
all表示所有的记录
any表示所有记录中的任意一条
some与any相同
in与any等价
exists表示子查询至少要返回一条记录
例如下面语句返回所有学生年龄都大于的班级对象
from Group g where <all (select sage from gstudents s)
下列语句返回在所有学生中有一个学生的年龄等于的班级
from Group g where = any (select sage from gstudents s)
或者
from Group g where = some(select sage from gstudents s)
或者
from Group g where in (select sage from gstudents s)
order by子句
查询返回列表可以按照任何返回的类或者组件的属性排序
from Student s order by sname asc
连接查询
与SQL一样HQL也支持连接查询如内连接外连接和交叉连接
inner join内连接
left outer join左外连接
rigth outer join右外连接
full join全连接但不常用
下面我重点介绍下内连接查询左外连接和或外连接和内连接大同小异而全连接几乎没有使用得到的地方
inner join可以简写为join例如在查询得到的Group对象时内连接取得对应的Student对象实现的程序代码如下
Student stu = null;
Group group = null;
Query query = sessioncreateQuery(from Group g join gstudents);
List list = querylist();
Object obj[] = null;
for(int i = ; i < listsize(); i++)
{
obj = (Object[])listget(i);
group = (Group)obj[];//group是数组是第一个对象
stu = (Student)obj[];//stu是数组的第二个对象
Systemoutprintln(stugetName()+属于+groupgetName());
}
Criteria Query方式
当查询数据时往往需要设置查询条件在SQL或HQL语句中查询条件常常放在where子句中此处Hibernate还支持Criteria查询这种查询方式把查询条件封装为一个Criteria对象在实际应用中可以使用Session的createCriteria()方法构建一个orghibernateCriteria实例然后把具体的查询条件通过Criteria的add方法加入到Criteria实例中这样程序员可以在不使用SQL甚至HQL的情况下进行数据查询如下 public void criteriaDEMO()
{
Session session = HibernateUtilcurrentSession();
Criteria criteria = sessioncreateCriteria(TRegisterclass);//生成一个Criteria实例
criteriaadd(Restrictionseq(userNamefengyan));//等价于where name = fengyan
List list = criterialist();
TRegister user = (TRegister)listget();
Systemoutprintln(usergetUserName());
}
常用的查询限制方法
上面代码中 Restrictionseq()方法表示equal即等于的情况Restrictions类提供了查询限制机制它提供了许多方法以实现查询限制
Restrictionseq()equal=
RestrictionsallEq() 参数为Map对象使用key/value进行多个等于的对比相当于多个 Restrictionseq()的效果
Restrictionsgt()greaterthan<
Restrictionslt()lessthan<
Restrictionslelessequal<=
Restrictionsbetween()对应SQL的between子句
Restrictionslike()对应SQL的like子句
Restrictionsin()对应SQL的in子句
Restrictionsand()and 关系
Restrictionsor()or 关系
RestrictionsisNull()判断属性是否为空为空返回true否则返回false
RestrictionsisNoyNull()与上面的相反
Orderasc()根据传入的字段进行升序排序
Orderdesc()与上相反
MatchModeEXACT字符串中精确匹配相当于like value
MatchModeANYWHERE字符串在中间位置相当于like%value%
MatchModeSTART字符串在最前面相当于likevalue%
MatchModeEND字符串在最后相当于like%value
下面是几个查询限制的例子
查询学生名字以t开关的所有Student对象
Criteria criertia = sessioncreateCriteria(Studentclass);
criteriaadd(Restrictionslike(name t%));
List list = criterialist();
Student stu = (Student)listget();
或者
Criteria criertia = sessioncreateCriteria(Studentclass);
criteriaadd(Restrictionslike(name tMatchModeSTART));
List list = criterialist();
Student stu = (Student)listget();
查询学生姓名在BillJack和Tom之间所有的Student对象
String[] names = {BillJackTom};
Criteria criertia = sessioncreateCriteria(Studentclass);
criteriaadd(Restrictionsin(name names));
List list = criterialist();
Student stu = (Student)listget();
查询学生年龄(age)等于或为空(null)的所有学生对象
Criteria criertia = sessioncreateCriteria(Studentclass);
criteriaadd(Restrictionseq(age new Integer()));
criteriaadd(RestrictionsisNull(age));
List list = criterialist();
Student stu = (Student)listget();
查询学生姓名以字母F开头的所有Student对象并按姓名升序排序
Criteria criertia = sessioncreateCriteria(Studentclass);
criteriaadd(Restrictionslike(name F%));
criteriaaddOrder(Orderasc(name));
List list = criterialist();
Student stu = (Student)listget();
注意调用Orderasc的方法应该是CriteriaaddOrder()方法
连接限制
Criteria查询中使用FetchMode来实现连接限制在HQL语句中可以通过fetch关键字来表示预先抓取(Eager fetching)如下
from Group g
left join fetch gstudents s
where gname like %
可以使用Criteria的API完成同样的功能如下
Criteria criertia = sessioncreateCriteria(Groupclass);
criteriasetFetchMode(students FetchModeEAGER);
criteriaadd(Restrictionslike(name MatchModeEND));
List list = criterialist();
以上两种方式编写的代码都使用相同的SQL语句来完成它们的功能如下
select g* s* from Group g
left outer join Student s
on gid = sgroup_id
where gname like %
Native SQL查询
本地SQL查询指的是直接使用本地数据库的SQL语言进行查询这样做对于将 原来的SQL/JDBC程序迁移到Hibernate应用很有用
创建一个基于SQL的Query
Native SQL查询是通过SQLQuery接口来控制的它通过调用SessioncreateSQLQuery()方法来获得如
String sql = select {s*} from t_student s where sage>;
//{}用来引用数据表的别名{s*}表示使用s来做为t_student表的别名
SQLQuery sqlQuery = sessioncreateSQLQuery(sql);
sqlQueryaddEntity(sStudentclass);
List list = sqlQuerylist();
for(int i = ; i < listsize(); i++)
{
Student stu = (Student)listget(i);
}
//createSQLQuery(String sql)利用传入的sql参数构造一个SQLQuery实例使用该方法时还需要传入查询的实体类因此在配合使用SQLQuery的addEntity()方法一起使用
命名SQL查询
与HQL的命名查询相似也可以将 本地的SQK查询语句定义在映射文件中然后像调用一个命名HQL查询一样专题报道调用命名SQL查询
如 </class>
<sqlquery name=QueryStudents>
<![CDATA[
select {s*} from t_student s where sage >
]]>
<return alias=s class=Student />
</sqlquery>
</hibernatemapping>配合以上配置我们可以如下编写代码来查询 Query query = sessiongetNamedQuery(QueryStudents);
List list = querylist();
for(int i = ; i < listsize();i++)
{
Student stu = (Student)listget(i);
}
也可以在命名查询是设定参数如下 <sqlquery name=QueryStudents>
<![CDATA[
select {s*} from t_student s where sage > :age
]]>
<return alias=s class=Student />
</sqlquery>
</hibernatemapping>程序代码 Query query = sessiongetNamedQuery(QueryStudents);
querysetInteger(age);
List list = querylist();
for(int i = ; i < listsize();i++)
{
Student stu = (Student)listget(i);
}自定义insert update和delete语句
Hibernate x的映射文件中新添加<sql_insert><sql_update><sqldelete>个标记可以使用这个标记自定义自己的insert updatedelete语句如 </class>
<sqlinsert>
insert into t_student(nameageid) values(???)
</sqlinsert>
<sqlupdate>
update t_student set name=?age=? where id=?
</sqlupdate>
<sqldelete>
delete from t_student where id = ?
</sqldelete>
</hibernatemapping>对于以上自定义的SQL语句要注意以下几点
insert 和update语句中定义的字段必须和映射文件声明的属性相应一个都不能少
在insert 和update语句中属性出现的顺序必须和映射文件中的顺序一样
在insert语句中主键id总是放在最后
在程序中实现以上自定义的insert语句如下 Student stu = new Student();
stusetName(Bill);
stusetAge();
sessionsave(stu);如果不想在insert或update语句中包括所有属性则可以在属性定义时 加上insert =false或update=false如下 <property name = name type=string insert = false update=false/>
<sqlinsert>
insert into t_student(ageid) values(??)
</sqlinert>