Hibernate检索方式(如何去查询数据,检索------查询也)

--导航对象图检索方式:根据已经获取的对象然后通过get方法来导航到其他对象。

--OID检索方式:按照对象的OID来检索对象,主要是session.get()方法,和session.load()方法

--HQL检索方式:使用面向对象的HQL查询语言

--QBC检索方式:使用QBC(Query By Criteria) API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。

--本地SQL检索方式:使用本地数据库的SQL查询语句

 

HQL(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语言有些相似,在Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式,它有如下功能:

--在查询语句中设定各种查询条件

--支持投影查询,即仅检索出独享的部分属性

--支持分页查询

--支持连接查询

--支持分组查询,允许使用HAVING和GROUP BY 关键字

--提供内聚函数,如sum(),min()和max()

--支持子查询

--支持动态绑定参数

--能够调用 用户定义的SQL函数 或标准的SQL函数

 

HQL检索方式包括以下步骤:

         --通过Session的createQuery()方法穿件一个Query对象,它包括一个HQL查询语句,HQL查询语句中可以包含命名参数(即占位符)

         --动态绑定参数

         --调用Query相关方法执行查询语句

Query接口支持方法链编程风格,它的setXxx()方法返回自身实例,而不是void类型

HQL vs SQL

         --HQL查询语句是面向对象的,Hibernate负责解析HQL查询语句,然后根据对象—关系映射文件中的映射信息,把HQL查询语句翻译成相应的SQL语句。HQL查询语句中的主体是域模型中的类及类的属性

         --SQL查询语句是与关系数据库绑定在一起的。SQL查询语句中的主体是数据库表及表的字段。

 

绑定参数:

         --Hibernate的参数绑定机制依赖于JDBC API中的PreparedStatement的预定义SQL语句功能。

         --HQL参数绑定有两种形式:

                   按照参数名字绑定:在HQL查询语句中定义命名参数,命名参数以”:”开头。

                   按照参数位置绑定:在HQL查询语句中用”?”来定义参数位置

         --相关方法:

                   setEntity():把参数与一个持久化类绑定

                   setParameter():绑定任意类型的参数,该方法的第三个参数显示制定Hibernate 映射类型

HQL采用 ORDERBY 关键字对查询结果排序

 

 

public class Department {

   

    private Integer id;

    private String name;

   

    private Set<Employee> emps = new HashSet<Employee>();

 

public class Employee {

   

    private Integer id;

    private String name;

    private float salary;

    private String email;

    private Department dept;

 

 

<hibernate-mapping package="com.atguigu.hibernate.entities">

  <class name="Department" table="GG_DEPARTMENT">

    <id name="id" type="integer">

       <column name="ID" />

       <generator class="native" />       

    </id>

    <property name="name" type="java.lang.String" >

        <column name="NAME"/>

    </property>

    <set name="emps" table="GG_EMPLOYEE" inverse="true" lazy="true">

        <key column="DEPT_ID" />

        <one-to-many class="com.atguigu.hibernate.entities.Employee"/>

    </set>

  </class>

</hibernate-mapping>

 

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.atguigu.hibernate.entities">

  <class name="Employee" table="GG_EMPLOYEE">

    <id name="id" type="integer">

        <column name="id" />

        <generator class="native" />

    </id>

    <property name="name" type="string">

        <column name="NAME"></column>

    </property>

    <property name="salary" type="float">

        <column name="SALARY"></column>

    </property>

   

    <property name="email" type="string">

        <column name="EMAIL"></column>

    </property>

   

    <many-to-one name="dept" class="com.atguigu.hibernate.entities.Department">

        <column name="DEPT_ID"></column>

    </many-to-one>

 

  </class>

</hibernate-mapping>

 

public class HibernateTest01 {

   

    private SessionFactory sessionFactory;

    private Session session;

    private Transaction transaction;

   

    @Before

    public void init(){

       Configuration conf = new Configuration().configure();

       ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();

       sessionFactory = conf.buildSessionFactory(serviceRegistry);

       session = sessionFactory.openSession();

       transaction = session.beginTransaction();

    }

    @After

    public void destroy(){

       transaction.commit();

       session.close();

       sessionFactory.close();

    }

   

    @Test

    public void testHQLNamedParameter(){

       //HQL查询语句除了可以使用占位符以外,还可以使用命名参数

      

       //1.创建Query对象

       //基于命名参数

       String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";

       Query query = session.createQuery(hql);

      

       //2.动态绑定参数,根据命名参数的话 ,根据名字来写而不是根据位置来写

       query.setFloat("sal", 7000).setString("email", "%a%");//含有a的

      

      

       //3.执行查询

       List<Employee> emps = query.list();

       System.out.println(emps.size());

    }

   

    @Test

    public void testHQL(){

      

       //1.创建Query对象

       //基于位置参数

       String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? ORDER BY e.salary";

       Query query = session.createQuery(hql);

      

       //2.动态绑定参数

       //Query对象调用setXxx 方法支持方法链的变成风格

       query.setFloat(0, 6000).setString(1, "%a%");//含有a的

      

       //3.执行查询

       List<Employee> emps = query.list();

       System.out.println(emps.size());

    }

    @Test

    public void testHQLSupprotEntityParameter(){

      

       //1.创建Query对象

       //基于位置参数,参数类型支持实体类类型

       String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept = ? ORDER BY e.salary";

       Query query = session.createQuery(hql);

      

       //2.动态绑定参数

       //Query对象调用setXxx 方法支持方法链的变成风格

       Department dept = new Department();

       dept.setId(80);

      

       query.setFloat(0, 6000)

           .setString(1, "%a%")//含有a的

           .setEntity(2, dept);

      

       //3.执行查询

       List<Employee> emps = query.list();

       System.out.println(emps.size());

    /*Hibernate:

           select

               employee0_.id as id1_1_,

               employee0_.NAME as NAME2_1_,

               employee0_.SALARY as SALARY3_1_,

               employee0_.EMAIL as EMAIL4_1_,

               employee0_.DEPT_ID as DEPT_ID5_1_

           from

               GG_EMPLOYEE employee0_

           where

               employee0_.SALARY>?

               and (

                   employee0_.EMAIL like ?

               )

               and employee0_.DEPT_ID=?

           order by

               employee0_.SALARY*/

    }

}

小结:

1.创建Query查询的三个基本步骤:

         ①:创建Query对象;②:绑定参数;③:执行查询;

         2.在写占位符的时候我们可以使用” ?”,也可以写命名参数;

         3.Query对象调用setXxx方法支持方法链的变成风格

         4.我们在写占位符参数的时候,也可以是实体类类型

         5.我们可以在HQL语句后面添加ORDER BY 排序

 

分页查询:

         --setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中索引位置,索引位置的起始值为0.默认情况下,Query从查询结果中的第一个对象开始检索。

         --setMaxResults(int maxResults):设定一次最多检索出的对象的数目,在默认情况下,Query和Criteria接口检索出查询结果中所有的对象。

 

    //HQL分页查询

    @Test

    public void testPageQuery(){

       String hql = "FROM Employee";

       Query query = session.createQuery(hql);

       int pageNo = 3;//第三页

       int pageSize = 5;//每页5条数据

       List<Employee> emps =

       query.setFirstResult((pageNo-1) * pageSize)

           .setMaxResults(pageSize).list();

      

       System.out.println(emps);

      

    }

 

//HQL命名查询

在映射文件中定义命名查询语句

 --Hibernate允许在映射文件中定义字符串形式的查询语句。

 --<query>元素用于定义一个HQL查询语句它和<class>元素并列

<query name=”findNewsByTitle”>

         <![CDATA[

         FROM News n WHERE n.title LIKE :title

]]>

</query>

--在程序中通过Session的getNamedQuery()方法获取查询语句对应的Query对象

 

  <query name="salaryEmps">

    <![CDATA[

        FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal

    ]]>

  </query>

 

 

         //HQL命名查询 :可以把HQL语句外置话,放到配置文件里面(放到CDATA块里面)

         @Test

         public void testNamedQuery(){

                  

                   Query query = session.getNamedQuery("salaryEmps");

                   List<Employee> emps = query.setFloat("minSal", 5000)

                                                                           .setFloat("maxSal", 10000).list();

                   System.out.println(emps.size());

         }

        

 

投影查询:

查询结果仅包含实体的部分属性,通过SELECT 关键字实现。

Query的list()方法返回的集合中包含的是数组类型的元素,每个对象数组代表查询结果的一条记录

可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录,使程序代码能完全运用面向对象的语句来访问查询结果集。

可以通过DISTINCT关键字来保证查询结果不会返回重复元素

 

//HQL投影查询查询部分属性,默认情况下查询结果返回的一个Object类型的数组

    @Test

    public void testFieldQuery(){

       String hql = "SELECT e.email,e.salary,e.dept " +

              "FROM Employee e " +

              "WHERE e.dept = :dept";

       Query query = session.createQuery(hql);

      

       Department dept = new Department();

       dept.setId(80);

       List<Object[]> result = query.setEntity("dept", dept).list();

       for(Object[] objs : result){

           System.out.println(Arrays.asList(objs));

       }

    }

    //在对应的持久化类当中写一个对应的构造器,然后可以返回一个对象的集合

    @Test

    public void testFieldQuery2(){

       //因为对数组操作不方便,所以我们把数组封装成对象

       //但前提是在持久化类当中确实提供了这样的一个构造器

       String hql = "SELECT new Employee(e.email,e.salary,e.dept) " +

              "FROM Employee e " +

              "WHERE e.dept = :dept";

       Query query = session.createQuery(hql);

       Department dept = new Department();

       dept.setId(80);

       List<Employee> result = query.setEntity("dept", dept).list();

       for(Employee emp : result){

           System.out.println(emp);

       }

    }

 

报表查询:

报表查询用于对数据分组和统计,与SQL一样,HQL利用GROUP BY 关键字对数据分组,用HAVING关键字对分组数据设定约束条件。

 

在HQL查询语句中可以调用以下聚集函数

--count()

--min()

--max()

--sum()

--avg()

 

 

    //在HQL里面可以用分组函数(gourp by ,having)

    @Test

    public void testGourpBy(){

       //在hql查询语句中我们可以使用GROUP BY ,HAVING ,还可以使用聚集函数

       String hql = "SELECT min(e.salary),max(e.salary) " +

              "FROM Employee e " +

              "GROUP BY e.dept " +

              "HAVING min(salary) > :minSal";

       Query query = session.createQuery(hql)

                     .setFloat("minSal",5000);

       List<Object[]> result = query.list();

       for(Object[] objs :result){

           System.out.println(Arrays.asList(objs));

       }

    }