(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 支持在查询中使用子查询。一个子查询必须被圆括号包围起来。
n连接(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
可以要求立即返回关联的集合对象,如:
java代码:from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
对于没有关联的实体,如何使用join呢?
对于没有关联的实体,想要使用join,可以采用本地查询的方式,使用sql来实现,比如:
s.createSQLQuery("select um.*,dm.* from tbl_user2 um left join tbl_dep dm on um.age=dm.uuid")
.addEntity("um",UserModel.class).addEntity("dm",DepModel.class);
1:新增
2:load、 get
3:修改
4:按条件查询
(1)传入条件值的方法:?或 :名称,索引从0开始
(2)给参数赋值
(3)返回对象
(4)返回多个属性,形成Object[]
(5)getByCondition的Hibernate版实现
5:删除
6:分页
Query q = sess.createQuery("from DomesticCat cat");
q.setFirstResult(20);
q.setMaxResults(10);
List cats = q.list();
也可以使用你的数据库的Native SQL语言来查询数据。这对你在要使用数据库的
某些特性的时候(比如说在查询提示或者Oracle中的 CONNECT关键字),这是非常有
用的。这就能够扫清你把原来直接使用SQL/JDBC 的程序迁移到基于 Hibernate应用
的道路上的障碍。
使用SQLQuery
对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行
Session.createSQLQuery()获取这个接口。下面来描述如何使用这个API进行查询。
标量查询(Scalar queries)
s.createSQLQuery(“select uuid,name from tbl_user”).list();
它将返回一个Object[]组成的List,Hibernate会使用ResultSetMetadata来判定返回的标量值的实际顺序和类型。你也可以使用scalar来明确指明类型,如:
s.createSQLQuery("select * from tbl_user").addScalar("id", LongType.INSTANCE)
id字段就明确是long型,当然你也可以指定很多个字段的类型。
实体查询(Entity queries)
上面的查询都是返回标量值的,也就是从resultset中返回的“裸”数据。下面展示如何通过addEntity()让原生查询返回实体对象。
(1) s.createSQLQuery("select * from tbl_user").addEntity(UserModel.class);
(2) s.createSQLQuery(“select uuid,userId from tbl_user2”).addEntity (UserModel.class); //一定要把表的所有字段罗列出来
(3) s.createSQLQuery("select {um}.uuid as {um.uuid},{um}.name as {um.name} from tbl_user {um}").addEntity("um",UserModel.class);
功能跟第二个差不多,也要把表的所有字段都罗列出来
(4)简单点的写法:s.createSQLQuery("select * from tbl_user2 um")
.addEntity("um",UserModel.class);
(5)添加条件的示例:
s.createSQLQuery("select * from tbl_user where uuid=? and name like ?").addEntity(UserModel.class).setString(0, "3").setString(1,"%na%");
命名Sql查询
可以在映射文档中定义查询的名字,然后就可以象调用一个命名的 HQL 查询一样直接调用命名 SQL查询.在这种情况下,我们不 需要调用 addEntity() 方法。
在hbm.xml中配置,示例如下:
java代码:<sql-query name="users">
<return alias="um" class="cn.javass.h3.hello.UserModel"/>
select um.name as {um.name},
um.age as {um.age},
um.uuid as {um.uuid}
from tbl_user um
where um.name like :name
</sql-query>
注意:因为要返回一个对象,所以要把表的所有字段都罗列上,否则会报错“列名无效”,其实是在反射向对象赋值的时候,从sql的返回中得不到这个数据。
程序里面调用示例:Query q = s.getNamedQuery(um.getClass().getName()
+".users").setString("name", "%n%");
命名Sql查询--使用return-property
使用 <return-property> 你可以明确的告诉 Hibernate 使用哪些字段别名,这取代了使用 {}-语法 来让 Hibernate 注入它自己的别名。
在hbm.xml中配置,示例如下:
java代码:<sql-query name="users">
<return alias="um" class="cn.javass.h3.hello.UserModel">
<return-property name="name" column="umName"></return-property>
<return-property name="uuid" column="uuid"></return-property>
<return-property name="age" column="age"></return-property>
</return>
select um.name as umName,
um.age as age,
um.uuid as uuid
from tbl_user um
where um.name like :name
</sql-query>
具有一个直观的、可扩展的条件查询API是Hibernate的特色。
创建一个Criteria 实例
org.hibernate.Criteria接口表示特定持久类的一个查询。Session是 Criteria实例的工厂。
java代码:Criteria crit = sess.createCriteria(Cat.class);
crit.setMaxResults(50);
List cats = crit.list();
限制结果集内容
一个单独的查询条件是org.hibernate.criterion.Criterion 接口的一个实例org.hibernate.criterion.Restrictions类 定义了获得某些内置Criterion类型的工厂方法。
java代码:List list = s.createCriteria(UserModel.class)
.add(Restrictions.eq("uuid", "3"))
.add(Restrictions.like("name", "%n%"))
.list();
约束可以按照逻辑分组,示例如下:
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.or(
Restrictions.eq( "age", new Integer(0) ),
Restrictions.isNull("age")
)
).list();
对结果集排序
可以使用 org.hibernate.criterion.Order 来为查询结果排序。示例如下:
java代码:List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "F%")
.addOrder( Order.asc("name") )
.addOrder( Order.desc("age") )
.setMaxResults(50)
.list();
1:假如有如下程序,需要向数据库里面加如100000条数据:
java代码:Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
}
tx.commit();
session.close();
这个程序很显然不能正常运行,会抛出内存溢出的例外。按照前面讲过的原理,Hibernate的save方法是先把数据放到内存里面,数据太多,导致内存溢出。
那么该如何解决呢?
解决方案:
1:首先将 hibernate.jdbc.batch_size的批量抓取数量参数设置到一个合适值(比如,10 - 50 之间),同时最好关闭二级缓存,如果有的话。
2:批量插入,一个可行的方案如下:
java代码:for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) {
//将本批数据插入数据库,并释放内存
session.flush();
session.clear();
}
}
批量更新的做法跟这个类似
1:默认的Hibernate是有缓存的,称之为一级缓存。
2:也可以使用StatelessSession,来表示不实现一级缓存,也不和二级缓存和查询缓存交互
3:StatelessSession是低层的抽象,和底层JDBC相当接近
java代码:StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers") .scroll(ScrollMode.FORWARD_ONLY);
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
session.update(customer);
} tx.commit(); session.close();