2010年4月11日 01:14:46
hibernate 查询语言:HQL
【注意:HQL的关键字不区分大小写,但类名和属性名有。】
【*在写HQL语句的时候不是通过表名进行查询,而是类............】
【*要注意查询结果的返回类型,如果是查询对象则返回的是该对象,如果是查属性,则返回的是与
该类型相同的属性列表。】
【*当语句中有条件限制符时,要注意加上单引号,如.....like '小%'】
【*如果查询多个属性则返回的是由Object数组组成的list——每个数组代表一组属性。
数组的长度取决于select语句中属性的个数】
【*查询多个属性,并且返回的是一个具体的类型(如过觉得Object不够对象化的话),而不是Object
注意必须写构造方法,包括无参的(原则上要求)】
【*可以使用别名进行查询,可以使用as关键子也可以不用】
【实体对象查询】【重要】
*采用select 查询实体对象,必须使用别名
【注意list和iterate的区别】
* 采用迭代接口(Iterator)进行查询
当缓存中没有数据的时候会有"N+1"问题出现:
N:发出N条语句到数据库进行查询(每个记录一条语句)
1:发出查询id列表的语句
原因:迭代接口使用缓存(session),通过查询出来的id到缓存中去找,找不到就会到数据库中去找
在有缓存的前提下使用iterate会提高效率
*list默认不使用缓存,会往缓存中放入数据
【条件查询】
简单条件查询
* 可以采用?方式进行查询,代表一个参数
* 参数的索引从0开始
* 可以采用参数名称的方式,例如:
Iterator iter = session.createQuery("select name from Student where name like :name")
.setParameter("name", "小%")
.list()
.iterator();
上面的方法采用了方法链的方式
*采用:参数名称的方式2:in方法:
Query query = session.createQuery("select name from Student where id in(:myids)");
Object ids[] = new Object[]{1,2,3};
query.setParameterList("myids",ids);
* 附加日期条件:
Query query = session.createQuery("select name from Student where date_format(createTime,'%Y-%m-%d')=?");
query.setParameter(0,"2010-04-10");
* 附加日期条件2
* 【注意】写的MM,而不是小写的mm m是小时中的分钟数 M是年中的月份
* 【重要】掌握定义日期的方法
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Query query = session.createQuery("select name from Student where createTime between ? and ?");
//要求参数必须是一个日期
Date beginTime=new Date(),endTime=new Date();
try {
beginTime = sdf.parse("2010-02-10 00:00:00");
endTime = sdf.parse("2010-04-10 23:59:59");
} catch (ParseException e) {
e.printStackTrace();
}
【使用SQL语句】:
Query query = session.createSQLQuery("select * from student");
Iterator iter = query.list().iterator();
【外置命名查询】
*将查询语句放在程序外部——放在映射文件中,可以是任何一个映射文件,使用的是query标签
*注意:为了避免XML文件中的标签与查询语句中的字符相冲突,一般将查询语句放在CDATA中:
<query name="getStudents">
<![CDATA[
SELECT s FROM Student s WHERE s.id > ?
]]>
</query>
*在程序内部这样子调用并设置参数:
Query query = session.getNamedQuery("getStudents")
.setParameter(0, 2);
注意:多个外置名称查询的命名不能相同
【查询过滤器】
*在映射文件中定义过滤器:
<!-- 定义一个过滤器 ,并带有参数,如果带了参数那么在启用该过滤器的时候就必须设置参数否则会有错误-->
<filter-def name="myfilter">
<filter-param name="id_filter" type="integer"/>
</filter-def>
<!-- 定义一个过滤器没有带参数 -->
<filter-def name="myfilter_2"><!--
<filter-param name="name_filter" type="string"/>
--></filter-def>
*在class标签内引用:
<filter name="myfilter" condition="id < :id_filter"/>
<!-- 直接将过滤条件写出来 -->
<filter name="myfilter_2" condition="name like '%桂'"/>
在程序中:session.enableFilter("myfilter").setParameter("id_filter", 3);
【分页查询】
setFirstResult()设置了开始显示的记录,0为第一条记录
setMaxResults() 设置了一次显示的最多记录数,可以用来做分页显示。
【采用对象导航查询】【重要】
例子:select s.name,s.id from Student s where s.classes.name like '%3
【连接查询】【重要】
//右连接
Query query = session.createQuery("select s.name,c.name from Student s right join s.classes c");
//左连接
// Query query = session.createQuery("select s.name,c.name from Student s left join s.classes c");
//默认为iner join ,iner可以不显式加上
// Query query = session.createQuery("select s.name,c.name from Student s join s.classes c");
【统计查询】【重要】
//这样会返回一个list,然后在从list中获取数据,这样显得不太方便,可以让其返回一个值
//List studentCount= session.createQuery("select count(*) from Student").list();
Long studentCount= (Long)session.createQuery("select count(*) from Student").uniqueResult();
【DML风格的查询】(不建议用hibernate来进行批量修改,因为不会与缓存同步,建议用sql语句来进行批量操作)
session.createQuery("update Student s set s.name = ? where s.id < ?")
.setParameter(0, "书桃")
.setParameter(1, 5)
.executeUpdate();
【使用CriteriaAPI】
参见CriteriaAPITest.java