Hibernate框架(三)Hibernate查询

Hibernate框架(三)Hibernate查询

  • get=>oid查询
  • 对象属性导航查询
  • HQL查询
  • Criteria
  • 原生SQL

HQL查询

Hibernate Query Language:hibernate查询语言,该查询语言是面向对象的查询语言.
HQL语句中绝对不可能出现与数据库相关的信息,都是与对象相关的信息,该语言是Hibernate独有的语言,只能在hibernate中使用.

  1. 书写HQL语句
  2. 创建查询对象
  3. 执行查询

语法

1、基础语法

    //书写HQL语句
    //String hql = "select c from Customer c ";
    String hql = "from Customer ";//简单写法
    //创建查询对象
    Query query = session.createQuery(hql);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

2、投影查询

//查询一个属性
    //书写HQL语句
    String hql = "select c.cust_name from Customer c ";
    //创建查询对象
    Query query = session.createQuery(hql);
    //执行查询
    List<String> list = query.list();
    System.out.println(list);

//查询两个属性封装到数组
    //书写HQL语句
    String hql = "select c.cust_id,c.cust_name from Customer c ";
    //创建查询对象
    Query query = session.createQuery(hql);
    //执行查询
    List<Object[]> list = query.list();
    for (Object[] objects : list) {
        System.out.println(Arrays.toString(objects));
    }

//查询多个属性封装到对象
    //书写HQL语句
    String hql = "select new Customer(cust_id,cust_name) from Customer ";
    //创建查询对象
    Query query = session.createQuery(hql);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

3、条件查询

//问号占位符
    //书写HQL语句
    String hql = " from Customer  where cust_name like ? ";
    //创建查询对象
    Query query = session.createQuery(hql);
    query.setParameter(0, "张%");//从0开始
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

//命名占位符
    //书写HQL语句
    String hql = " from Customer  where cust_name like :name ";
    //创建查询对象
    Query query = session.createQuery(hql);
    query.setParameter("name", "张%");//从0开始
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

4、分页查询

//书写HQL语句
String hql = " from Customer  ";
//创建查询对象
Query query = session.createQuery(hql);
//设置分页
query.setFirstResult(0);//起始页,limit第一个问号
query.setMaxResults(2);//页大小,limit第二个问号
//执行查询
List<Customer> list = query.list();
System.out.println(list);

5、排序查询

asc升序/desc降序

    //书写HQL语句
    String hql = " from Customer order by cust_id desc ";
    //创建查询对象
    Query query = session.createQuery(hql);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

6、聚合查询

  • count
  • max
  • min
  • avg
  • sum

    //书写HQL语句
    String hql = " select count(c) from Customer c ";
    //创建查询对象
    Query query = session.createQuery(hql);
    //执行查询
    Long count = (Long) query.uniqueResult();
    System.out.println(count);
    

多表查询

原生SQL

交叉连接(笛卡尔积,开发中避免出现)

内连接
隐式内连接
select * from a,b where a.id = b.aid;
显示内连接
select * from a inner join b on a.id = b.aid;
外连接
左外连接
select * from a left join b on a.id = b.aid;
右外连接
select * from a right join b on a.id = b.aid;

HQL

内连接

//书写HQL语句
String hql = "from Customer c inner join c.linkMen ";
//创建查询对象
Query query = session.createQuery(hql);
//执行查询
List<Object[]> list = query.list();
for (Object[] objects : list) {
    System.out.println(Arrays.toString(objects));
}

迫切内连接

//书写HQL语句
String hql = "from Customer c inner join fetch c.linkMen ";
//创建查询对象
Query query = session.createQuery(hql);
//执行查询
List<Customer> list = query.list();
System.out.println(list);

左/右外连接

//书写HQL语句
String hql = "from Customer c left join c.linkMen ";
//创建查询对象
Query query = session.createQuery(hql);
//执行查询
List<Object[]> list = query.list();
for (Object[] objects : list) {
    System.out.println(Arrays.toString(objects));
}

迫切左/右外连接

//书写HQL语句
String hql = "from Customer c inner join fetch c.linkMen ";
//创建查询对象
Query query = session.createQuery(hql);
//执行查询
List<Customer> list = query.list();
System.out.println(list);

迫切连接:将查询结果封装成对象.

HQL多表查询只适合比较简单的多表查询,业务比较复杂的,仍然要用原生SQL查询.

Criteria查询

hibernate框架中独有的查询方式.Criteria是无语句面向对象查询.Criteria一般用于单表查询.

语法

1、基本查询

//创建Criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//执行查询
List<Customer> list = criteria.list();
System.out.println(list);

2、条件查询

//创建Criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置查询参数,between函数,第一个参数是要查询的属性,第二个是查询条件,第三个是查询条件,and包含多个条件
criteria.add(Restrictions.and(Restrictions.between("cust_id", 3l, 5l),
        Restrictions.like("cust_name", "张%")));
//执行查询
List<Customer> list = criteria.list();
System.out.println(list);

3、分页查询

//创建Criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置查询参数
criteria.setFirstResult(0);//limit的第一个参数
criteria.setMaxResults(2);//limit的第二个参数
//执行查询
List<Customer> list = criteria.list();
System.out.println(list);

4、排序查询

    //创建Criteria查询对象
    Criteria criteria = session.createCriteria(Customer.class);
    //设置查询参数
    criteria.addOrder(Order.asc("cust_id")); //升序
    //criteria.addOrder(Order.desc("cust_id"));//降序
    //执行查询
    List<Customer> list = criteria.list();
    System.out.println(list);   

5、聚合查询

  • count
  • max
  • min
  • avg
  • sum

    //创建Criteria查询对象
    Criteria criteria = session.createCriteria(Customer.class);
    //设置查询参数,setProjection添加聚合函数,统计数量
    criteria.setProjection(Projections.count("cust_id"));
    //执行查询
    long count = (long) criteria.uniqueResult();
    System.out.println(count);
    

离线Criteria查询对象

获得离线查询对象
//web层
    //获得离线查询对象
    DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
    //添加条件
    dc.add(Restrictions.like("cust_name", "张%"));
执行离线查询对象
//dao层
    //将离线Criteria对象与session关联
    Criteria criteria = dc.getExecutableCriteria(session);
    //执行查询
    List<Customer> list = criteria.list();
    System.out.println(list);

原生SQL

使用数组封装每行记录

    //书写SQL语句
    String sql = "select * from cst_customer";
    //执行sql查询对象
    SQLQuery query = session.createSQLQuery(sql);
    //指定将结果封装到哪个对象中
    query.addEntity(Customer.class);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

指定将结果封装到哪个对象

//书写SQL语句
    String sql = "select * from cst_customer where cust_name like ?";
    //执行sql查询对象
    SQLQuery query = session.createSQLQuery(sql);
    //设置参数值
    query.setParameter(0, "张%");
    //指定将结果封装到哪个对象中
    query.addEntity(Customer.class);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

参数查询:SQL中可以使用问号|命名占位符

    //书写SQL语句
    String sql = "select * from cst_customer where cust_name like :name";
    //执行sql查询对象
    SQLQuery query = session.createSQLQuery(sql);
    //设置参数值
    query.setParameter("name", "张%");
    //指定将结果封装到哪个对象中
    query.addEntity(Customer.class);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

分页查询:Limit语法

    //书写SQL语句
    String sql = "select * from cst_customer limit ?,?";
    //执行sql查询对象
    SQLQuery query = session.createSQLQuery(sql);
    //设置参数值
    query.setParameter(0, 0);//设置起始页
    query.setParameter(1, 2);//设置页大小
    //指定将结果封装到哪个对象中
    query.addEntity(Customer.class);
    //执行查询
    List<Customer> list = query.list();
    System.out.println(list);

hibernate查询策略

类级别查询策略

API
  • get方法:调用时立即查询数据库,不会应用任何加载策略
  • load方法:默认情况下,执行load方法时,不会立即查询数据库,使用时才会执行查询.load方法会应用类级别加载策略
配置
<!-- lazy属性:懒加载|延迟加载 
            true(默认):懒加载|延迟加载
            false:立即加载
-->
<class name="Customer" table="cst_customer" lazy="false" > 
实现原理

在懒加载时,load不会立即查询,但是仍会返回一个对象,返回的对象要查询的对象的代理对象,这个代理对象会封装当前操作的session,在获得对象的属性时,能够根据关联的session加载数据

注意事项

返回的代理对象,初始化操作一定要确保在session关闭之前完成,不然会抛no-session异常.

关联级别查询策略

集合加载策略

一对多|多对多

lazy属性:决定集合加载策略
    true(默认值):懒加载|延迟加载
    false:立即加载
    extra:极其懒惰,在查询集合数量时,只查询数量


fetch属性:指定集合的加载方式
    select(默认值):在加载集合时使用单表查询加载
    join:在加载集合时会使用左外连接查询
        注:fetch=join时,lazy属性失效.
    subselect:子查询,加载多个客户的集合时,子查询才有效,如果只是加载一个客户的集合,subselect与select一样

<set name="linkMen" inverse="true" lazy="true" fetch="subselect" >
    <key column="lkm_cust_id" ></key>
    <one-to-many class="LinkMan" />
</set>
属性加载策略

多对一

lazy属性:是否懒加载
    proxy(默认值):由对方的类级别策略代我决定
    false:立即加载

fetch属性:决定加载方式
    select(默认值):单表查询加载关联数据
    join:使用多表查询同时加载关联数据.        
注意:使用join时,lazy属性失效

<many-to-one name="customer" column="lkm_cust_id" class="Customer" lazy="false" fetch="join" ></many-to-one>

查询策略总结

结论:查询策略中涉及的所有属性都使用默认值.

问题1. sql语句打印n+1问题

解决方案:batch-size属性:选择一次加载几个客户的集合,默认值:1

<set name="linkMen" inverse="true" batch-size="2">
问题2.no-session问题

dao返回的代理对象.Service中关闭了session.在web层使用了代理对象时,session已经关闭

解决方案:
1. 不使用getCurrentSession.自己将session与线程绑定
2. 使用过滤器,在过滤器的后处理器代码中关闭session.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值