Hibernate实现按条件查询的方式
1:最重要的按条件查询的方法是使用Query接口,使用HQL
2:本地查询(native sql):就是使用标准的sql,也是通过Query接口来实现
3:按条件查询(Query By Criteria,QBC):使用动态的,面向对象的方式来创建查询
4:按样例查询(Query By Example,简写QBE):类似我们自己写的getByCondition(不常用)
5:命名查询:在hbm.xml中配置hql语句,在程序里面通过名称来创建Query接口(不常用)
Query的list方法
一个查询通常在调用 list() 时被执行,执行结果会完全装载进内存中的一个集合,查询返回的对象处于持久状态。如果你知道的查询只会返回一个对象,可使用list()的快捷方式uniqueResult()
当我们调用了q.list()后:
1:对HQL进行语义分析,分析出model来
2:根据model类型和cfg.xml中映射文件的注册来找到相应的hbm.xml文件
3:根据hbm.xml文件和model,来解析HQL,从而实现动态的把HQL转换成对应的sql,(从hql---〉sql这个过程是非常复杂的,不但区分不同的数据库,还包括了对sql进行自动的优化),这里只能简单的示例如下:
select 字段列表(来自hbm.xml) from 表名(来自hbm.xml) where 条件
4:真正用JDBC执行sql,把数据从数据库中查询出来到rs里面
5:从结果集---〉Model集合(或对象数组),然后返回model集合(或对象数组)
Iterator和List
某些情况下,你可以使用iterate()方法得到更好的性能。 这通常是你预期返回的结果在session,或二级缓存(second-level cache)中已经存在时的情况。 如若不然,iterate()会比list()慢,而且可能简单查询也需要进行多次数据库访问: iterate()会首先使用1条语句得到所有对象的持久化标识(identifiers),再根据持久化标识执行n条附加的select语句实例化实际的对象。
分页查询:
Query q = session.createQuery("from DomesticCat").setFirstResult(1).setMaxResults(10);
List cats = q.list();
Query q = session.createQuery("from Order o where id = ? ").setParameter(0, 1L);
Query q0 = session.createQuery("from Order o where id in (:ids)").setParameterList("ids", new Long[]{1l,2l,3l,4l});
Query q1 = session.createQuery("from Order o where id = ? ").setLong(0, 1);
Query q2 = session.createQuery("from Order o where id > :id").setLong("id", 1);
List<Order> rs = q0.list();
List<Integer> lst = new ArrayList<Integer>();
lst.add(14);
lst.add(15);
lst.add(17);
String hql = "from Students s where s.SId in (:lst)";
Query q = session.createQuery(hql);
q.setParameterList("lst",lst);
// 以一个实类作为参数条件
hql = "from Students s where s.class=:class";
q.setEntity("class",session.get(Class.class,1));
// 根据给的参数匹配对应的类型Type hiberntae里的类
hql = "from Students s where s.SId=? or s.SName=?";
Query q = session.createQuery(hql);
q.setParameters(new Object [] { 14,"update" },new Type [] { new IntegerType(),new StringType() });
//时间类型的参数
List students = session.createQuery("select s.id, s.name from Student s where date_format(s.createTime, '%Y-%m')=?").setParameter(0, "2008-02").list();
//查询2008-01-10到2008-02-15创建的学生
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List students = session.createQuery("select s.id, s.name from Student s where s.createTime between ? and ?").setParameter(0, sdf.parse("2008-01-10 00:00:00"))
.setParameter(1, sdf.parse("2008-02-15 23:59:59")).list();
HQL介绍
Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL。但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承、多态和关联之类的概念。
看个示例,看看sql和HQL的相同与不同:
Sql:select * from tbl_user where uuid=‘123’
HQL:select Object(o) from UserModel o where o.uuid=‘123’
HQL特点
1:HQL对Java类和属性是大小写敏感的,对其他不是大小写敏感的。
2:上sql和HQL是可以基本转换的,因为按照Hibernate的实现原理,最终运行的还是sql,只不过是自动生成的而已。
3:HQL支持内连接和外连接
4:HQL支持使用聚集函数,如:count、avg、sum、min、max等
5:HQL支持order by 和 group by
6:HQL支持条件表达式,如:in、like、between等
select子句
1:直接返回对象集合,形如:select o from UserModel o
2:返回某个特定类型的集合,形如:select o.name from UserModel o
3:返回Object[],形如:select o.uuid,o.name from UserModel o
4:返回List,形如:select new List(o.uuid,o.name) from UserModel o
5:返回任意的对象,形如:select new cn.javass.h3.hello.A(o.uuid,o.name) from UserModel o ,这要求A对象有一个构造方法是传入这两个参数
6:返回Map类型,形如:select new Map(o.uuid as Id,o.name as N) from UserModel o ,返回的结果,以as后面的别名做map的key,对应的数据做值
from子句
1:直接from对象,形如: from UserModel
2:可以分配别名,形如:from UserModel as um , as关键字可以省略
3:如果from后面有多个对象,形如:from UserModel,DepModel ,相当于多表联合查询,返回他们的笛卡尔积
聚集函数
1:受支持的有avg,sum,min,max,count
2:关键字 distinct 与all 也可以使用,它们具有与 SQL 相同的语义,比如:
select count(distinct o.name) from UserModel o
where子句
1:如果前面没有指派别名,那就直接使用属性名
2:如果指派了别名,必须使用别名.属性的方式
3:在where子句中允许使用的表达式包括大多数在 SQL中使用的表达式,包括:
(1)数学运算符 +,-,*,/
(2)二进制比较运算符 =, >=, <=, <>, !=, like
(3)逻辑运算符 and,or,not
(4)括号 ( ),表示分组
(5)in, not in, between, is null, is not null, is empty, is not empty, member of and not member of
(6)字符串连接符 ...||... or concat(...,...)
(7)current_date(), current_time(), and current_timestamp()
(8)second(...)、minute(...)、hour(...)、day(...)、month(...) 和 year(...)
(9)EJB-QL 3.0 定义的任何功能或操作符:substring(), trim(), lower(), upper(), length(),locate(), abs(), sqrt(), bit_length(), mod()
(10)coalesce() 和 nullif()
(11)str() 把数字或者时间值转换为可读的字符串
(12)cast(... as ...),其第二个参数是某 Hibernate 类型的名字,以及 extract(... from ...),只要 ANSI cast() 和 extract() 被底层数据库支持
(13)HQL index() 函数,作用于 join 的有序集合的别名。
(14)HQL 函数,把集合作为参数:size(), minelement(), maxelement(), minindex(), maxindex(),还有特别的 elements() 和 indices 函数,可以与数量词加以限定:some, all, exists, any, in。
(15)任何数据库支持的 SQL 标量函数,比如 sign(), trunc(), rtrim(), sin()
(16)JDBC 风格的参数传入 ?
(17)命名参数 :name,:start_date,:x1
(18)SQL 直接常量 'foo', 69, 6.66E+2, '1970-01-01 10:00:01.0'
(19)Java public static final 类型的常量 eg.Color.TABBY
group by 子句
1:对于返回聚集值的查询,可以按照任何属性进行分组
2:可以使用having子句
3:sql中的聚集函数,可以出现在having子句中
4:group by 子句与 order by 子句中都不能包含算术表达式
5:不能group by 某个实体对象,必须明确的列出所有的聚集属性
order by 子句
查询返回的列表(list)可以按照一个返回的类或组件(components)中的任何属性进行排序,可选的 asc 或 desc 关键字指明了按照升序或降序进行排序。
子查询
对于支持子查询的数据库,Hibernate 支持在查询中使用子查询。一个子查询必须被圆括号包围起来。
join
1:Hibernate可以在相关联的实体间使用join,类似于sql,支持inner join、left outer join、right outer join、full join(全连接,并不常用)。
2:inner join可以简写成join,left outer join 和right outer join在简写的时候可以把outer去掉。
with
通过 HQL 的 with 关键字,你可以提供额外的 join 条件。
如:from Cat as cat left join cat.kittens as kitten with kitten.bodyWeight > 10.0
fetch
可以要求立即返回关联的集合对象,如:
from Cat as cat inner join fetch cat.mate left join fetch cat.kittens
flush方法
每间隔一段时间,Session会执行一些必需的SQL语句来把内存中对象的状态同步到JDBC连接中。这个过程被称为刷出(flush),默认会在下面的时间点执行:
1:在某些查询执行之前
2:在调用org.hibernate.Transaction.commit()的时候
3:在调用Session.flush()的时候
涉及的 SQL 语句会按照下面的顺序发出执行:
1. 所有对实体进行插入的语句,其顺序按照对象执行save() 的时间顺序
2. 所有对实体进行更新的语句
3. 所有进行集合删除的语句
4. 所有对集合元素进行删除,更新或者插入的语句
5. 所有进行集合插入的语句
6. 所有对实体进行删除的语句,其顺序按照对象执行 delete() 的时间顺序
除非你明确地发出了flush()指令,关于Session何时会执行这些JDBC调用是完全无法保证的,只能保证它们执行的前后顺序。 当然,Hibernate保证,Query.list(..)绝对不会返回已经失效的数据,也不会返回错误数据。
lock方法:也允许程序重新关联某个对象到一个新 session 上。不过,该脱管对象必须是没有修改过的。示例如:s.lock(um, LockMode.READ);
注意:lock主要还是用在事务处理上,关联对象只是一个附带的功能