Hibernate入门最后一天第四天,我们进行查询方式的更进一步的细化:

  先看一下大致的Hibernate的提供的查询的方式:

    1.对象导航查询

    2.OID查询

    3.HQL查询

    4.QBC查询

    5.本地SQL查询

  使用框架,我们更加关注的是前四种查询的方式。

接下来逐条介绍:

  1.对象导航查询
    例如昨天的客户联系人的一对多:
    根据id查询到客户,再根据客户下的所有联系人
    这个查询过程称为对象导航
    就是得到表示的那个set就可以
    Set<LinkMan> set = cust.getSet_LinkMan();

    /**
* 对象导航查询(顺便OID也在里面了)
* @author jiangbei01
*
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //查询客户中的所有联系人
Customer cust = session.get(Customer.class, 1);
//利用对象导航查询到所有联系人
//做法就是 得到那个表示所有联系人的set集合
Set<LinkMan> set = cust.getSet_LinkMan();
System.out.println(set.size());
//提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

  2.OID查询
    根据id查询某一条记录(返回的是对象)
    也就是session.get方法实现
    Customer cust = session.get(Customer.class, 1);

  3.HQL查询
    使用HQL语言(用到Query对象,昨天只演示了查询所有)==写语句
    HQL与SQL最大的不同是:
        HQL操作实体类
        SQL操作表

    HQL常用语句:
        查询所有 === from 实体类名称

/**
* HQL Query对象查询所有
* @author jiangbei01
*
*/
@SuppressWarnings("deprecation")
@Test
public void query2(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery("from Customer");
//调用方法
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer.getCustLevel());
}
//提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

        条件查询 === from 实体类名称 where 实体类属性=? ... 写法与SQL基本类似:

          from 实体类名称 where 属性 like ?

/**
* HQL条件查询 第一步都是创建query对象
* 模糊查询极其类似,不再赘述举例这里 参数为String类型的即可(%浪%)
*/
@Test
public void query3(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"from Customer c where c.cid=?");
//设置条件值,也就是向?设置值,一般都是用这个方法,而较少去使用其它重载方法
//第一个参数为int ?问号的位置,第二个为Object,这里必须注意:!!
//pstmt里面?从1 开始 ,这里从0开始!
query.setParameter(0, 1);
//调用方法
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer.getCustLevel());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

        
        排序查询 === from 实体类名称 order by 属性 acs

    /**
*演示排序
*/
@Test
public void query4(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"from Customer order by cid asc");
//调用方法
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer.getCid());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

        分页查询 === mysql中实现分页使用的是关键字 limit,注意此时hibernate不认识Limit这个方言!

/**
*演示分页
*/
@Test
public void query5(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"from Customer");
//设置开始位置
query.setFirstResult(0);
//设置每页的记录数
query.setMaxResults(5); //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

        使用的是query的封装的两个方法:
        投影查询 === (用的不是很多,原因是查到所有后部分也简单)
        投影的概念:查的是部分字段 例如 SELECT cid FROM t_stu
        HQL与SQL这里也是极其相似
          select 属性名1,属性名2 from 实体类名称(注意不能 写* ,写*查询所有应直接 from ...)
        聚合函数 === 常用的COUNT() SUM() MAX/MIN() AVG()
  HQL写法:
      select count(*) from 实体类名称
    使用这种接收只有某个的结果
      Object o = query.uniqueResult();
      注意此处返回值不能直接强转成int,因为此处o是long类型
      应当先转成long类型,再转
      Long不能直接强转,而是使用intValue()返回基本类型的值

/**
*演示聚合函数
*/
@Test
public void query6(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //得到Query对象 ,显示已过时,待解决
Query query = session.createQuery(
"select count(*) from Customer");
//只返回某个值,而不用list
Object o = query.uniqueResult();
System.out.println(o); //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}
}

  

  4.QBC查询 (实际开发更倾向于此而少写HQL)
    用到的是 Criteria对象 ==不写语句,这是与HQL不同的部分,而是使用方法操作实体类进行的操作
  包含的也是这些:
    查询所有:
      得到对象,调用方法即可

/**
*演示QBC查询所有
*/
@Test
public void query6(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//调用方法实现
List<Customer> list = criteria.list();
//遍历结果集
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

    条件查询:
      通过方法控制条件

    /**
*演示QBC条件查询
*/
@Test
public void query5(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//使用add()方法设置条件的值,更多请百度Restrictions静态类的用法
criteria.add(Restrictions.eq("cid", 1));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

  以下概念不再赘述,直接见案例
    排序查询:

/**
*演示QBC排序查询
*/
@Test
public void query4(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//设置对哪个属性进行排序,包括排序方式和排序规则(似乎不如HQL方便)
criteria.addOrder(Order.desc("cid")); List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

    分页查询:

    /**
*演示QBC分页查询
*/
@Test
public void query3(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//也是调方法,和HQL有点相似,设置分页的两个数据,注意:凡是设置的方法,一般都是先打set前缀
criteria.setFirstResult(0);
criteria.setMaxResults(2); List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustName());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

    统计查询:
,  统计记录条数等:

/**
*演示QBC统计查询
*/
@Test
public void query2(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建对象 ,显示已过时,待解决
Criteria criteria = session.createCriteria(Customer.class);
//设置操作,其它操作举一反三
criteria.setProjection(Projections.rowCount());
//调用方法
Object o = criteria.uniqueResult();
Long l = (Long) o;
int r = l.intValue(); System.out.println(r); //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

离线查询:
  步骤:
    创建对象
    设置操作
    调用方法
    离线查询:
  之前的criteria是通过session查询的,是依赖session的
  场景例子:希望在条件查询时就在servlet中实现条件的拼接
  就是可以离线的操作

/**
*演示QBC离线查询
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //创建离线
DetachedCriteria detachedCriteria = DetachedCriteria
.forClass(Customer.class);
//最终执行的时候才用session
Criteria criteria = detachedCriteria.getExecutableCriteria(session); //再执行
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCustPhone());
} //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

  5.本地SQL查询
    SQLQuery对象,使用本地SQL查询(前面有类似的案例,用的少的不再赘述)

    当然,这里重点应该关注前4种查询方式

  使用了上面的单表查询后,来看看HQL如何进行多表查询

    HQL多表查询(达到会用的水平先)
      回顾mysql的一般多表查询:
            内连接 INNER JOIN ON
            左外连接 LEFT OUTER JOIN ON
            右外连接 RIGHT OUTER JOIN ON
    HQL实现多表查询:
      1.内连接
      2.左外连接
      3.右外连接
      4.迫切内连接
      5.迫切左外连接(没有右外!勿擅自创造)

  再次强调,HQL操作的是实体类,而不是表!

    1.HQL内连接:
      from Customer c inner join c.set_LinkMan
      注意点:join后加的是表示联系人的set集合,并且后面没有on!

/**
*演示HQL内连接
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //HQL使用的是Query对象
Query query = session.createQuery("from Customer c inner join c.set_LinkMan");
List list = query.list();
//提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

  2.迫切内连接和内连接的底层实现是一样的
    迫切内连接返回的list每部分是对象
    而内连接返回的list每部分是数组
    from Customer c inner join fetch c.set_LinkMan

  3.左外连接与迫切左外连接:
    from Customer c left outer join c.set_LinkMan
    from Customer c left outer join fetch c.set_LinkMan
    同样的,左外连接返回的每部分是数组
    迫切左外连接返回的是对象

迫切与普通连接查询的区别:

 我们可以看到采用左外连接查询返回的结果集中包含的是对象数组,对象数组中的每个元素存放了一对相互关联的Customer对象和Order对象,
而迫切左外连接会返回Customer对象,与Customer对象相关联的Order对象存放在Customer对象的集合元素对象中,
这就是迫切左外连接和左外连接查询的其中一个区别(这两种检索生成的SQL语句是一样的) 

以上两种用法与1都相差无几。

Hibernate检索策略:
  主要分为两类:
    立即检索:
      一调用get()方法马上发送SQL语句去查询
    延迟检索:
      调用load()方法,不会马上发送语句,
  只有得到对象里面的值的时候,也就是什么时候用那个值
  才发送语句,查询数据库,调用load()时,初始里面只有传入的id值
  验证的方式是debug看发送语句的时机(F6一步一步走)

  延迟查询中又分两类:(默认会有相关的延迟优化方式,自己修改的机会少)
  类级别的延迟:
    返回一个实体类的对象
  在class标签上设置lazy值(选值见下)

  关联级别的延迟:
    查询某个客户,再查询客户里的所有联系人,
    查询客户所有联系人的过程是否需要延迟
      关联级别的延迟方式也可以自己修改(当然,默认的优化已经可以,作了解)
      修改方式是在映射文件中进行配置
      根据客户得到联系人,则配置客户的映射文件
      在set标签上设置属性:
  fetch:值select(默认)
  lazy:值true 延迟(默认)
      false 不延迟(遇到要用时都查出来给你)
      extra 极其延迟(要什么给的什么,用size就只发送count(*))

/**
*演示立即查询与延迟查询
*/
@Test
public void query1(){
//注意规范写法
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null; try{
//得到工厂
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//一调用get方法,马上去查询
Customer cust = session.get(Customer.class, 1);
System.out.println(cust.getCustName()); Customer cust1 = session.load(Customer.class, 2);//此时Customer中只有一个id值
System.out.println(cust1.getCustName());//去拿它的名字时才发语句去查询 //提交事务
tx.commit();
}catch(Exception e){
//事务回滚
tx.rollback();
}finally{
//关闭资源
session.close();
sessionFactory.close();
}
}

Hibernate的批量抓取(会用)
比如使用场景,需要查询所有客户(返回list)的联系人
可以先查出list,再逐个遍历(性能低)
这种对象导航仅仅实现了功能,却使得性能低下(发送了很多次的语句)

完成批量抓取的优化是通过映射文件的配置完成的
在set标签上配置属性 batch-size=""
这里面配置一个整形,没有固定值,值越大发的语句越少,性能越高(当然应当根据数据库记录数调优)
(可以查看底层SQL,使用的是in(?,?...)的形式,减少了语句的发送)

Hibernate第四天——查询方式的更多相关文章

  1. Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加

    Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略: 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja ...

  2. hibernate的三种查询方式

    hibernate的三种查询方式 目录 hibernate的三种查询方式 1.HQL查询 1.1.SQL概述 1.2.实体查询 1.3.带where的查询 1.3.属性查询 1.4.实体的更新和删除 ...

  3. hibernate学习笔记6--Criteria查询方式、完整小练习(开发步骤)

    一.Criteria查询方式没有sql语了,因此更加面向对象一些.Criteria是一种比HQL更面向对象的查询方式:Criteria的创建方式: Criteria c = s.createCrite ...

  4. Hibernate之HQL检索(查询)方式

    HQL(Hibernate Query Language)是面向对象的查询语言,与SQL非常相似.在Hibernate中,HQL是使用最广泛的检索方式. 具有下面经常使用功能: (1)在查询语句中,能 ...

  5. Hibernate的几种查询方式-HQL,QBC,QBE,离线查询,复合查询,分页查询

    HQL查询方式 这一种我最常用,也是最喜欢用的,因为它写起来灵活直观,而且与所熟悉的SQL的语法差不太多.条件查询.分页查询.连接查询.嵌套查询,写起来与SQL语法基本一致,唯一不同的就是把表名换成了 ...

  6. sessionFactory的创建和四种查询方式

    1,关于sessionFactory的创建 5.0版本之前,下面这种方式在5.0及之后,可能会出问题,建议修改为5.0之后的方式 // 实例化Configuration Configuration c ...

  7. Spring Data Jpa的四种查询方式

    一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...

  8. hibernate 查询方式汇总

    主要摘自  http://blog.sina.com.cn/s/blog_7ffb8dd501014a6o.html ,http://blog.csdn.net/xingtianyiyun/artic ...

  9. Hibernate查询方式汇总

    Hibernate总的来说共有三种查询方式:HQL.QBC和SQL三种.但是细分可以有如下几种: 一.HQL查询方式    这一种我最常用,也是最喜欢用的,因为它写起来灵活直观,而且与所熟悉的SQL的 ...

随机推荐

  1. leetcode 之 Same Tree

    1.题目描述 Given two binary trees, write a function to check if they are the same or not. Two binary tre ...

  2. 将虚拟网络连接到 ExpressRoute 线路

    本文通过使用 Resource Manager 部署模型和 Azure 门户,帮助将虚拟网络 (VNets) 链接到 Azure ExpressRoute 线路. 虚拟网络可以在同一个订阅中,也可以属 ...

  3. TreeView控件概述、属性与方法

    1.作用:用于显示Node结点的分层列表.2.添加到控件箱菜单命令:工程 | 部件,在部件对话框中选择:Microsoft Windows Common Controls 6.03.TreeView控 ...

  4. iOS设计模式 - 代理

    iOS设计模式 - 代理 原理图 说明 1. 代理模式大家都用过,但用抽象基类NSProxy实现代理估计鲜有人用 2. 本人用NSProxy实现了代理模式,对于理解消息转发机制有点帮助 源码 http ...

  5. SDWebImage动画加载图片

    SDWebImage动画加载图片 效果 源码 https://github.com/YouXianMing/Animations // // PictureCell.m // SDWebImageLo ...

  6. 封装CoreGraphics的API简化绘图操作

    封装CoreGraphics的API简化绘图操作 效果 说明 1. 将CoreGraphics的API接口抽象为对象,让绘图变得简单易懂 2. 简化常用的绘制操作 3. 源码长期更新 源码 https ...

  7. linux下手动安装git教程

    Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.而国外的GitHub和国内的Coding都是项目的托管平台.但是在使用git工具的时候,第一步要学会如何安装gi ...

  8. Automapper实现自动映射

    出于安全考虑,在后台与前台进行数据传输时,往往不会直接传输实体模型,而是使用Dto(Data transfer object 数据传输对象),这样在后台往前台传递数据时可以省略不必要的信息,只保留必要 ...

  9. Spring MVC Interceptor

    1 在spring-servlet.xml中进行如下配置 <mvc:interceptors> <mvc:interceptor> <mvc:mapping path=& ...

  10. java 扁平化输出json所有节点key/value

    本章主要介绍用java实现扁平化输出json所有节点key/value(包含所有内层子节点) 1.json结构 目的输出bill_list下的datalist里的子节点key/value 2.实现代码 ...