Hibernate query language。hql查询中关键字不区分大小写,但是类和属性都是区分大小写的。
1.简单属性查询。
单一属性查询,返回属性结果集列表,元素类型和实体类的相应的类型一致。
- for (Iterator iter=students.iterator(); iter.hasNext();) {
- String name = (String)iter.next();
- System.out.println(name);
- }
List students = session.createQuery("select name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}
//返回结果集属性列表,元素类型和实体类中的属性类型一致
多个属性查询,多个属性查询返回数组对象,对象数组的长度取决于属性的个数,对象数组中的元素类型与实体类中属性一致。
- List students = session.createQuery("select id, name from Student").list();
- for (Iterator iter=students.iterator(); iter.hasNext();) {
- Object[] obj = (Object[])iter.next();
- System.out.println(obj[0] + ", " + obj[1]);
- }
List students = session.createQuery("select id, name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
2.实体对象查询
List students = session.createQuery("from Student").list();
当然这种hql语句,可以使用别名,as可以省去,如:from Student as s,若是使用select关键字,则必须使用别名。如:select s from Student as s.但是不支持select * from Student格式。
查询中使用list和Iterate区别:
list查询是直接运行查询的结果,所以只有一句sql语句。而iterate方法则有可能会产生N+1条sql语句。这是怎么回事呢?要理解N+1条语句,首先得弄明白iterate是如何执行查询的?
首先发出一条查询对象ID的语句,然后根据对象的ID到缓存(缓存的概念上篇博客已经提到)中查找,若是存在查询出此对象的其他的属性,否则会发出N条语句,此时的N语句,是刚才第一次查询的记录条数。这种现象就是N+1sql语句。
其中list是默认情况下都发出sql语句,查询出的结果会放到缓存中,但是它不会利用缓存,即使放进去,下次执行时,仍然继续发出sql语句。
而:iterate默认情况下会利用缓存,若是缓存中有则不会发出N+1条语句。
3.条件查询。
这种方式就是传入参数,使用参数占位符“?”。也可以使用“:参数名”
java代码如下:
- List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
- .setParameter(0, "%0%")
- .list();
- List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
- .setParameter("myname", "%0%")
- .list();
List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
.setParameter(0, "%0%")
.list();
List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
.setParameter("myname", "%0%")
.list();
4.使用原生sql语句。
和咱们原先写入的sql语句一样。在此不介绍了。
5.外置命名查询。
这个听起来有点晦涩,怎么理解呢?其实通俗的说就是把hql语句写在外面,写在映射文件中。使用标签:
- <query name="queryStudent">
- <![CDATA[
- select s from Student s where s.id <?
- ]]>
- </query>
<query name="queryStudent">
<![CDATA[
select s from Student s where s.id <?
]]>
</query>
那在程序中是如何使用此标签的呢?使用session.getNameQuery(),并进行赋值,代码如下:
- .setParameter(0, 10)
- .list();
List students = session.getNamedQuery("queryStudent")
.setParameter(0, 10)
.list();
6.查询过滤器。
这个是什么意思呢?过滤器大家很熟悉吧,不熟悉的可以参考我的以前博客<>.原来我们接触过编码过滤器,编码过滤器就是为了避免当时每个页面需要设置编码格式而提出的。这个查询过滤器其实也是这个意思。若是代码都需要某一句sql语句的话,可以考虑使用它。这样可以避免每次都写查询语句。
使用如下:首先在映射文件中配置标签:
- <filter-def name="testFilter">
- <filter-param type="integer" name="myid"/>
- </filter-def>
<filter-def name="testFilter">
<filter-param type="integer" name="myid"/>
</filter-def>
然后程序中如下使用并进行赋值:
- .setParameter("myid", 10);
session.enableFilter("testFilter")
.setParameter("myid", 10);
7.分页查询。
分页查询,这个肯定不陌生,因为在做drp项目时,做的最多的是分页,当时使用oracle数据库,分页查询涉及到三层嵌套。直接传入的参数为:每页的大小(记录数),页号。
Hibernate中给我们已经封装好了,只要设置开始的页号以及每页的大小即可,不用亲自动手写嵌套的sql语句。
代码如下:
- .setFirstResult(1)
- .setMaxResults(2)
- .list();
List students = session.createQuery("from Student")
.setFirstResult(1)
.setMaxResults(2)
.list();
8.对象导航查询。
这个什么意思呢?这个只要是用于一个类的属性是另一个类的引用。比如:student类中有一个classes属性。其中的classes也是一个类Class的引用。
当我们查询的时候可以这样使用:
- List students = session.createQuery("from Student s where s.classes.name like '%t%'")
- .list();
List students = session.createQuery("from Student s where s.classes.name like '%t%'")
.list();
相当于:s.getClasses.getName(),直接使用get后面的属性,然后首字母小写。
这种语法,是不是很熟悉?想想我们在哪是不是也用过?想起来了吗?估计你猜出来啦,呵呵,是JSTL(jsp standard tag library)中。若是想进一步了解,可以参考我的博客哈,当时是转载滴貌似。
9.连接查询。
连接分为:内连接和外连接,其中外连接分为左连接,右连接,完全连接。这个跟数据库中的左右连接其实是一样的。我们通俗解释一下:
左连接:以左边为准,右边即使没哟匹配的,也要把这条记录查询出来,此时没有匹配的右边以null填充。
右连接:以右边为准,左边即使没有匹配的,也要把这条记录查询出来,此时没有匹配的左边以null填充。
完全连接:只要一方存在即可。
内连接:必须两方都存在才可以查询提取此记录。
10.统计查询。
其实就是查询count的记录数。其中查询出来的额count是long类型。
11.DML风格的操作。
DML?其实DML=Data Manipulate Language(数据操作语言),举个例子:
- session.createQuery("update Student s set s.name=? where s.id<?")
- .setParameter(0, "王斌")
- .setParameter(1, 2)
- .executeUpdate();
session.createQuery("update Student s set s.name=? where s.id<?")
.setParameter(0, "王斌")
.setParameter(1, 2)
.executeUpdate();
假若原来的名字是:李四,更新完数据库后变成王斌,若是我们此时取出数据,其姓名是李四还是王斌?按照道理应该是王斌,但是结果确实李四,若不信,可以自己去实践一下。
这个原因,是因为更新了数据库,但是缓存中没有更新,才会造成这种数据库和缓存不同步的问题。
所以,我们应该尽量不使用这种形式。扬其长避其短嘛。