[select|update|delete 子句]用于查询,更新和删除。
[from 类名列表]指定查询的持久化类所在的的数据表名。 [where 子句]给出查询的条件。 [group by 子句]用于对数据进行分组。 [order by 子句]对查询结果进行排序。 注意:除了Java类与属性的名称外,HQL查询语句对大小写并不敏感。 所以 SeLeCT 与 sELEct 以及 SELECT 是相同的,但是 org.hibernate.eg.FOO 并不等价于 org.hibernate.eg.Foo 并且 foo.barSet 也不等价于 foo.BARSET。 二、HQL语法详解 -----[select|update|delete]-------- select关键词后跟的是需要返回的对象或者对象属性,且属性必须属于from子句中给出的类列表。使用select可以直接存入一个List对象或直接封装为一个对象。 使用示例: 1、查询具体属性 select stu.cores.english from Student as stu; 上述语句查询出学生的英语成绩 2、查询并放入List对象 select new List(stu.id,stu.name) from Student as stu; 查询了学生的学号和名字,放入一个List中 3、查询并生成对象 select new Student(stu.id,stu.name) from Student as stu; 查询了学生的学号和名字,并生成一个Student对象。使用前提:Student类中存在相应的构造方法。 4、查询所有属性 from Student 多数情况下,我们可以为查询的实体对象指定一个别名,方便在其他地方引用。 from Student as stu update和delete是Hibernate3新加入的特性。这样我们更新数据库就有两种方式。 1、先修改持久化对象的值,之后提交事务更新数据。 2、使用HQL语句实现。不过不推荐这种方式。 ---------from子句----------- from子句是最简单的HQL,例如from Student,也可以写成 select s from Student s。它简单的返回Student类的所有实例。 ---------where子句---------- HQL也支持子查询,它通过where子句实现这一机制。where子句可以让用户缩小要返回的实例的列表范围。例如下面语句会返回所有名字为"kang"的Student实例: Query query = session.createQuery("from Student as stu where stu.name='kang'"); 1、where子句允许出现的表达式 数学操作:+,-,*,/ 真假比较操作:=, >=, <=, <>, !=, like 逻辑操作:and ,or, not 字符串连接:|| SQL标题函数 :如upper()和lower() 2、如果查询返回多条记录,可以用以下关键字来量化 all:表示所有的记录。 any:表示所有记录中的任意一条。 some:与any相同。 in:与any等价。 exists:表示子查询至少要返回一条记录。 查询示例: 返回所有学生年龄都大于18的班级对象 from Group g where 18<all (select s.age from g.students s) 返回在所有学生中有一个学生的年龄等于22的班级: from Group g where 22 = any (select s.age from g.students s) 或者 from Group g where 22= some(select s.age from g.students s) 或者 from Group g where 22 in (select s.age from g.students s) -----------Group by子句-------------- 在HQL语句中同样支持使用group by子句分组查询,还支持group by子句结合聚集函数的分组统计查询,大部分标准的SQL聚集函数都可以在HQL语句中使用,比如: count(),sum(),max(),min(),avg()等。(前提是数据库支持having语句,例如mysql不支持) count():统计记录条数。 min():求最小值。 max():求最大值。 sum():求和。 avg():求平均值。 例如,要取得Student实例的数量,可以编写如下HQL语句: select count(*) from Student 取得Student平均年龄的HQL语句: select avg(s.age) from Student as s 可以使用distinct去除重复的数据: select distinct s.age from Student as s 如下面的程序代码: String hql=”select count(user),user.age from User user group by user.age having count(user)>10 ”;//mysql不行 List list=session.createQuery(hql).list(); --------------order by子句------------ 查询返回列表可以按照任何返回的类或者组件的属性排序,asc为正序排列(从小到大),desc为降序排列(从大到小) 按照学生的学号正序排列 from Studen as stu order by stu.id 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 = session.createQuery("from Group g join g.students"); List list = query.list(); Object obj[] = null; for(int i = 0 ; i < list.size(); i++) { obj = (Object[])list.get(i); group = (Group)obj[0];//group是数组是第一个对象 stu = (Student)obj[1];//stu是数组的第二个对象 System.out.println(stu.getName()+"属于"+group.getName()); }
---------------子查询--------------- 对于支持子查询的数据库,Hibernate支持在查询中使用子查询。一个子查询必须被圆括号包围起来(经常是SQL聚集函数的圆括号)。 甚至相互关联的子查询(引用到外部查询中的别名的子查询)也是允许的。 from Cat as fatcat where fatcat.weight > (select avg(cat.weight) from DomesticCat cat) ---------------参数绑定-------------- Hibernate中对动态查询参数绑定提供了丰富的支持,那么什么是查询参数动态绑定呢?其实如果我们熟悉传统JDBC编程的话,我们就不难理解查询参数动态绑定, 如下代码传统JDBC的参数绑定: PrepareStatement pre=connection.prepare(“select * from User where user.name=?”); pre.setString(1,”xiaokang”); ResultSet rs=pre.executeQuery(); 在Hibernate中也提供了类似这种的查询参数绑定功能,而且在Hibernate中对这个功能还提供了比传统JDBC操作丰富的多的特性,在Hibernate中共存在4种参数绑 定的方式,下面我们将分别介绍: 1、按参数名称绑定: 在HQL语句中定义命名参数要用”:参数名”的形式,形式如下: Query query=session.createQuery(“from User user where user.name=:customername and user.customerage=:age ”); query.setString(“customername”,name); query.setInteger(“customerage”,age); 上面代码中用:customername和:customerage分别定义了命名参数customername和customerage,然后用Query接口的setXXX()方法设定名参数值,setXXX()方法包 含两个参数,分别是命名参数名称和命名参数实际值。 2、按参数位置邦定: 在HQL查询语句中用”?”来定义参数位置,形式如下: Query query=session.createQuery(“from User user where user.name=? and user.age =? ”); query.setString(0,name); query.setInteger(1,age); 同样使用setXXX()方法设定绑定参数,只不过这时setXXX()方法的第一个参数代表邦定参数在HQL语句中出现的位置编号(由0开始编号),第二个参数仍然代表参数实际值。 注:在实际开发中,提倡使用按名称邦定命名参数,因为这不但可以提供非常好的程序可读性,而且也提高了程序的易维护性,因为当查询参数的位置发生改变时,按名称邦定名参数的方式中是不需要调整程序代码的。 3、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。 4、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对象实例的属性值匹配到命名参数上,但是要求命名参数名称必须要与实体对象相应的属性同名。 这里还有一个特殊的setEntity()方法,它会把命名参数与一个持久化对象相关联,如下面代码所示: Customer customer=(Customer)session.load(Customer.class,”1”); Query query=session.createQuery(“from Order order where order.customer=:customer ”); query. setProperties(“customer”,customer); List list=query.list(); 上面的代码会生成类似如下的SQL语句: Select * from order where customer_ID=’1’; 三、如何使用HQL语句 HQL查询依赖于Query类,每个Query实例对应一个查询对象,使用HQL查询按如下步骤进行: 1.获取Hibernate Session对象 2.编写HQL语句 3.以HQL语句作为参数,调用Session的createQuery方法创建查询对象 4.如果HQL语句包含参数,则调用Query的setXxx方法为参数赋值 5.调用Query独享的list()或uniqueResult()方法返回查询结果列表 例如: Session s = null; try{ s = HibernateUtil.getSession();//获取session,前提HibernateUtil中有一个静态方法getSession String hql = "from Test as test where test.name=?"; Query query = s.createQuery(hql);//创建Query对象 query.setString(0,name);//设置参数 List list = query.list();//查询结果 for(Test test:list){//遍历 System.out.println(test.getName()); } }finally{ //finally表示数据库一定要被关闭 if(s!=null) s.close(); } } }