一、唯一标识OID的检索方式
这种方式是通过主键来查找的,调用方式如session.get(对象.class,OID)
,适用于获取单条数据.
二、HQL的检索方式
什么是HQL
HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似
在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式。
HQL与SQL的关系
HQL 查询语句是面向对象的,Hibernate负责解析HQL查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句。
HQL 查询语句中的主体是域模型中的类及类的属性。
SQL 查询语句是与关系数据库绑定在一起的,SQL查询语句中的主体是数据库表及表的字段。
注意:HQL语句的使用必须要开启事务,即调用createQuery方法必须要先开启事务,否则会报错:
org.hibernate.HibernateException: createQuery is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:334)
HQL支持以下几种查询:
1.HQL基本的查询格式
支持方法链的编程,即直接调用list()方法,例如:
session.createQuery("from Customer").list();//from后面写的是类名而不是表名
2.使用别名的方式
session.createQuery("from Customer c").list();//as 可以省略
session.createQuery("select c from Customer c").list();
3.排序查询
排序查询和SQL语句中的排序的语法是一样的
session.createQuery("from Customer order by cust_id").list(); //升序,默认asc可省略
session.createQuery("from Customer order by cust_id desc").list(); //降序
4.分页查询
Hibernate框架提供了分页的方法,咱们可以调用方法来完成分页,两个方法如下
setFirstResult(index) //从哪条记录开始,如果查询是从第一条开启,从0开始,取值参考(pageNo-1)*pageSize
setMaxResults(pageSize) //每页查询的记录条数
例如获取第一页的数据,每页有10条数据,可以这样写:
List<LinkMan> list = session.createQuery("from LinkMan").setFirstResult(0).setMaxResults(10).list();
5.带条件的查询
有3种方式:
- 按位置绑定参数的条件查询(指定下标值,默认从0开始)例如:
...
Query query = session.createQuery("from Linkman l where l.lkm_id >= ? and l.lkm_gender = ?");
query.setLong(0, 2L);
query.setString(1, "男");
List<Linkman> list = query.list();
...
- 按名称绑定参数的条件查询(HQL语句中的 ? 号换成 :名称 的方式),例如:
...
Query query = session.createQuery("from Linkman l where l.lkm_id >= :id and l.lkm_gender = :sex");
query.setLong("id", 2L);
query.setString("sex", "男");
List<Linkman> list = query.list();
...
- setParameter("?号的位置,默认从0开始",“参数的值”); 不用考虑参数的具体类型
或者setParameter(“绑定的名称”,“参数的值”); 例如:
...
Query query = session.createQuery("from Linkman l where l.lkm_id >= ? and l.lkm_gender = :sex");
query.setParameter(0, 2L);
query.setParameter("sex", "男");
List<Linkman> list = query.list();
...
注意:条件查询中的模糊查询的%是写在参数设置的方法里的,例如:
...
Query query = session.createQuery("from Linkman l where l.lkm_name like ?");
query.setParameter(0, "%o%"); //这里填写模糊查询的表达式
List<Linkman> list = query.list();
...
6.投影查询
投影查询就是想查询某一字段的值或者某几个字段的值.返回的结果有两种:
- 返回数组的集合
...
Query query = session.createQuery("select lkm_name,lkm_gender from Linkman");
List<Object[]> list = query.list();//返回的是数组的集合
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
...
输出的结果:
- 返回javabean集合
必须在javabean中提供指定字段的构造方法,例如:
public Linkman(String lkm_name, String lkm_gender) {
this.lkm_name = lkm_name;
this.lkm_gender = lkm_gender;
}
public Linkman() {
}
然后HQL语句也要做相应变化,例如:
...
Query query = session.createQuery("select new Linkman(lkm_name,lkm_gender) from Linkman where lkm_gender=?");
query.setParameter(0, "女");
List<Linkman> list = query.list();// 返回的是对象的集合
for (Linkman lm : list) {
System.out.println(lm);
}
...
7.聚合函数查询
HQL语句还能使用count() sum() avg() max() min()等聚合函数,例如:
/**
* avg聚合函数查询
*/
@Test
public void test10() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
List<Number> lis = session.createQuery("select avg(lkm_id) from Linkman ").list();
System.out.println(lis.get(0).longValue());
tr.commit();
}
/**
* max聚合函数查询
*/
@Test
public void test9() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
List<Number> lis = session.createQuery("select max(lkm_id) from Linkman ").list();
System.out.println(lis.get(0).intValue());
tr.commit();
}
/**
* sum聚合函数查询
*/
@Test
public void test8() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
List<Number> lis = session.createQuery("select sum(lkm_id) from Linkman ").list();
System.out.println(lis.get(0).intValue());
tr.commit();
}
/**
* count聚合函数查询
*/
@Test
public void test7() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
List<Number> lis = session.createQuery("select count(*) from Linkman ").list();
System.out.println(lis.get(0).intValue());
tr.commit();
}
三、QBC检索方式
QBC:Query By Criteria 按条件进行查询,非常适合用于条件查询,完全面向对象的方式调用
注意:使用qbc查询的前提也必须要开启事务,即调用createCriteria方法必须要先开启事务,否则回报如下错误:
org.hibernate.HibernateException: createCriteria is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invo
QBC查询支持以下几种查询:
1.简单查询
/**
* QBC的基本入门查询
*/
@Test
public void test1() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建QBC查询接口
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tr.commit();
}
2.排序查询
需要使用addOrder()的方法来设置参数,参数使用org.hibernate.criterion.Order对象的常量
/**
* QBC的排序查询
*/
@Test
public void test2() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建QBC查询接口
Criteria criteria = session.createCriteria(Customer.class);
criteria.addOrder(Order.desc("cust_id"));//按照属性cust_id降序排序
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tr.commit();
}
3.分页查询
QBC分页的方法和HQL分页的方式一样的,操作的是setFirstResult();和setMaxResults();这2个方法
/**
* QBC的分页查询
*/
@Test
public void test3() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
Criteria criteria = session.createCriteria(Linkman.class);
// 设置分页查询从第一条记录开始(pageNo-1)*pageSize, 查询3条数据,调用方式可以链式调用
List<Linkman> list = criteria.setFirstResult(0).setMaxResults(3).list();
for (Linkman linkman : list) {
System.out.println(linkman);
}
tr.commit();
}
4.条件查询
Criterion是查询条件的接口,Restrictions类是Hibernate框架提供的工具类,使用该工具类来设置查询条件,条件查询使用Criteria接口的add方法来传入条件,有以下条件可传:
- Restrictions.eq:相等
- Restrictions.gt:大于号
- Restrictions.ge:大于等于
- Restrictions.lt:小于
- Restrictions.le :小于等于
- Restrictions.between:在之间
- Restrictions.like:模糊查询
- Restrictions.in :范围
- Restrictions.and:并且
- Restrictions.or:或者
- Restrictions.isNull:空值查找
例如:
/**
* QBC的条件查询
*/
@Test
public void test4() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
Criteria criteria = session.createCriteria(Linkman.class);
//使用方法添加条件
criteria.add(Restrictions.eq("lkm_gender","男")); //等于男
//lkm_id大于等于2,小于5
criteria.add(Restrictions.and(Restrictions.ge("lkm_id",2L),Restrictions.lt("lkm_id",5L)));
List<Linkman> list = criteria.list();
for (Linkman linkman : list) {
System.out.println(linkman);
}
tr.commit();
}
/**
* QBC的条件查询之in查询
*/
@Test
public void test5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建QBC查询接口
Criteria criteria = session.createCriteria(Linkman.class);
// SQL:select * from cst_linkman where lkm_id in (1,2,5);
List<Long> params = new ArrayList<Long>();
params.add(1L);
params.add(2L);
params.add(5L);
// 使用in 方法查询
criteria.add(Restrictions.in("lkm_id", params));
List<Linkman> list = criteria.list();
for (Linkman linkman : list) {
System.out.println(linkman);
}
tr.commit();
}
5.聚合函数查询
Projection的聚合函数的接口,而Projections是Hibernate提供的工具类,使用该工具类设置聚合函数查询,常用的方法有:
例如:
/**
* QBC的聚合函数查询
*/
@Test
public void test6(){
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建QBC查询接口
Criteria criteria = session.createCriteria(Linkman.class);
//聚合函数count使用
criteria.setProjection(Projections.count("lkm_id"));
List<Number> list= criteria.list();
System.out.println(list.get(0).intValue());
tr.commit();
}
/**
* QBC的多次查询
*/
@Test
public void test8() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建QBC查询接口
Criteria criteria = session.createCriteria(Linkman.class);
// 聚合函数count使用
criteria.setProjection(Projections.count("lkm_id"));
// 查询count
List<Number> list = criteria.list();
System.out.println(list.get(0).intValue());
// 重置projection
criteria.setProjection(null);
List<Linkman> lms = criteria.list();
for (Linkman lm : lms) {
System.out.println(lm);
}
tr.commit();
}
提示:criteria.setProjection(null);也是有意义的,它是用于重置聚合函数的查询条件,比如你想在一个方法里面重复是用criteria.list();去查询结果,由于第一次已经使用了聚合函数,第二次如果不想使用,可以直接调用criteria.setProjection(null);来重置.
四、离线条件查询
离线条件查询使用的是DetachedCriteria接口进行查询,离线条件查询对象在创建的时候,不需要使用Session对象,只是在查询的时候使用Session对象即可。通常在web层就可以设置好查询条件,然后传入到service层使用,创建DetachedCriteria方式例如:
DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
然后就可以调用add方法添加各种条件了或者setProjection添加聚合函数,例如:
/**
* 离线查询
*/
@Test
public void test9() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建离线Criteria
DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
// 添加条件
criteria.add(Restrictions.eq("lkm_gender", "女"));
// 开始查询
List<Linkman> list = criteria.getExecutableCriteria(session).list();
for (Linkman linkman : list) {
System.out.println(linkman);
}
tr.commit();
}
五、SQL查询方式
如果喜欢手写sql语句的朋友,可以使用这种方式,通过session.createSQLQuery(sql语句);
的方式来执行sql查询.例如:
/**
* 把数据封装到对象中
*/
@Test
public void test2() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建的是SQL的查询的接口
SQLQuery query = session.createSQLQuery("select * from cst_linkman where lkm_gender = ?");
// 通过该方法关联实体类
query.addEntity(Linkman.class);
// 设置条件
query.setParameter(0,"男");
List<Linkman> list = query.list();
for (Linkman linkman : list) {
System.out.println(linkman);
}
tr.commit();
}
/**
* 测试SQL语句的查询,输出数组集合
*/
@Test
public void test1() {
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建的是SQL的查询的接口
SQLQuery query = session.createSQLQuery("select * from cst_linkman");
// 查询数据
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
tr.commit();
}