第五次作業(yè) hql查詢

注意:HQL語言,是基于對象進行查詢的,不是基于數(shù)據(jù)庫的表。

一、Hibernate 提供了以下幾種檢索對象的方式:

導航對象圖檢索方式: 根據(jù)已經(jīng)加載的對象導航到其他對象 OID 檢索方式: 按照對象的 OID 來檢索對象
HQL 檢索方式:使用面向?qū)ο蟮?HQL 查詢語言
QBC 檢索方式: 使用 QBC(Query By Criteria) API 來檢索對象. 這種
API 封裝了基于字符串形式的查詢語句, 提供了更加面向?qū)ο蟮牟樵兘涌?
本地 SQL 檢索方式: 使用本地數(shù)據(jù)庫的 SQL 查詢語句
二、HIbernate的HQL查詢

  1. HQL(Hibernate Query Language) 是面向?qū)ο蟮牟樵冋Z言, 它和 SQL 查詢語言有些相似. 在 Hibernate 提供的各種檢索方式中, HQL 是使用最廣的一種檢索方式. 它有如下功能:
    在查詢語句中設定各種查詢條件
  • 支持投影查詢, 即僅檢索出對象的部分屬性
  • 支持分頁查詢
  • 支持連接查詢
  • 支持分組查詢, 允許使用 HAVING 和 GROUP BY 關鍵字
  • 提供內(nèi)置聚集函數(shù), 如 sum(), min() 和 max()
  • 支持子查詢
  • 支持動態(tài)綁定參數(shù)
  • 能夠調(diào)用 用戶定義的 SQL 函數(shù)或標準的 SQL 函數(shù)
  1. HQL 檢索方式包括以下步驟:
    a、通過 Session 的 createQuery() 方法創(chuàng)建一個 Query 對象, 它包括一個 HQL 查詢語句. HQL 查詢語句中可以包含命名參數(shù)
    b、動態(tài)綁定參數(shù)
    c、調(diào)用 Query 相關方法執(zhí)行查詢語句.
    三、各種查詢示例代碼:
    1、首先搭建測試環(huán)境:
    兩個測試實體類:
Employee類:

public class Employee {

    private Integer id;
    private String name;
    private float salary;
    private String email;

    private Department dept;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getSalary() {
        return salary;
    }

    public void setSalary(float salary) {
        this.salary = salary;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Department getDept() {
        return dept;
    }

    public void setDept(Department dept) {
        this.dept = dept;
    }

    public Employee(float salary, String email, Department dept) {
        super();
        this.salary = salary;
        this.email = email;
        this.dept = dept;
    }

    public Employee() {

    }

    @Override
    public String toString() {
        return "Employee [id=" + id + "]";
    }   
}

Department類:

public class Department {
    private Integer id;
    private String name;
    private Set<Employee> emps=new HashSet<Employee>();

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Employee> getEmps() {
        return emps;
    }
    public void setEmps(Set<Employee> emps) {
        this.emps = emps;
    }
    @Override
    public String toString() {
        return "Department [id=" + id + ", name=" + name + "]";
    }   
}

2個實體類對應的hbm配置文件:

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-6-10 23:07:48 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.entity">
    <class name="Employee" table="EMPLOYEE">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="salary" type="float">
            <column name="SALARY" />
        </property>
        <property name="email" type="java.lang.String">
            <column name="EMAIL" />
        </property>
        <many-to-one name="dept" class="Department" >
            <column name="DEPT_ID" />
        </many-to-one>
    </class>
    <query name="salaryEmp">
      <![CDATA[   
       from Employee e where e.salary> :minSal and e.salary < :maxSal 
      ]]>
    </query>
</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">
<!-- Generated 2018-6-10 23:07:48 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.entity">
    <class name="Department" table="DEPARTMENT">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <set name="emps" table="EMPLOYEE" inverse="true" lazy="true">
            <key>
                <column name="DEPT_ID" />
            </key>
            <one-to-many class="Employee" />
        </set>
    </class>
</hibernate-mapping>

Hibernate配置文件:hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
    <!-- hibernate數(shù)據(jù)庫連接信息配置 -->
       <property name="connection.username">root</property>
       <property name="connection.password">root123</property>
       <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
       <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <!-- hibernate基本配置 -->  
    <!-- hibernate的數(shù)據(jù)庫方言 -->
       <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> 
       <property name="hbm2ddl.auto">update</property>
       <property name="show_sql">true</property>
       <property name="format_sql">true</property>
    <!--設置hibernate事務的隔離級別  -->
       <property name="connection.isolation">2</property>
    <!-- 需要關聯(lián)的hibernate映射文件 hbm.xml文件 -->
      <mapping resource="com/elgin/hibernate/entity/Department.hbm.xml"/> 
      <mapping resource="com/elgin/hibernate/entity/Employee.hbm.xml"/>   
    </session-factory>
</hibernate-configuration>

Hibernate查詢單元測試類:

public class HibernateTest2 {

    //如此聲明只為方便測試,生產(chǎn)環(huán)境不能這么用
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transcation;

    @Before
    public void init(){
        Configuration cfg=new Configuration().configure();
        ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
        sessionFactory=cfg.buildSessionFactory(serviceRegistry);
        session=sessionFactory.openSession();
        transcation=session.beginTransaction();
    }
    public void insert(int i){

            Employee employee=new Employee();
            employee.setName("name"+i);
            employee.setEmail("name"+i+"@qq.com");
            employee.setSalary(1000*i);
            session.save(employee);

    }
    @Test
    //初始化2個表中的數(shù)據(jù),方便查詢
    public void test(){
        for (int i = 14; i < 21; i++) {

            insert(i);
        }
    }

    @After
    public void destory(){
        transcation.commit();
        session.close();
        sessionFactory.close();
    }
}

上述類為基礎測試類,如下的測試代碼均需加入到上述類中運行。至此,測試環(huán)境搭建完成,下面逐一進行測試:
2 綁定參數(shù):

  • Hibernate 的參數(shù)綁定機制依賴于 JDBC API 中的 PreparedStatement 的預定義 SQL 語句功能.
  • HQL 的參數(shù)綁定由兩種形式:
    按參數(shù)名字綁定: 在 HQL 查詢語句中定義命名參數(shù), 命名參數(shù)以 “:” 開頭.
    按參數(shù)位置綁定: 在 HQL 查詢語句中用 “?”來定義參數(shù)位置
  • 相關方法:
    setEntity(): 把參數(shù)與一個持久化類綁定。
    setParameter(): 綁定任意類型的參數(shù). 該方法的第三個參數(shù)顯式指定 Hibernate 映射類型。
    測試代碼:
@Test
    public void testHQLNamedParameters(){
        //1.創(chuàng)建  Query 對象
        //  基于命名參數(shù)
        String HQL="FROM Employee e WHERE e.salary> :salary AND e.email LIKE :email";
        Query query=session.createQuery(HQL);

        //2. 動態(tài)綁定參數(shù)
        query.setFloat("salary", 6000).setString("email", "%a%");

        //3. 執(zhí)行查詢
        List<Employee> emps =  query.list();
        System.out.println(emps.size());

    }

    @Test
    public void testHQL(){
        //1.創(chuàng)建  Query 對象
        //  基于位置的參數(shù)
        String HQL="FROM Employee e WHERE e.salary> ? AND e.email LIKE ?";
        Query query=session.createQuery(HQL);

        //2. 動態(tài)綁定參數(shù)
        //  Query對象調(diào)用setXxx方法,支持方法鏈的編程
        query.setFloat(0, 6000).setString(1, "%a%");

        //3. 執(zhí)行查詢
        List<Employee> emps =  query.list();
        System.out.println(emps.size());

    }

3 分頁查詢:

  • setFirstResult(int firstResult): 設定從哪一個對象開始檢索, 參數(shù) firstResult表示這個對象在查詢結果中的索引位置, 索引位置的起始值為 0. 默認情況下, Query 從查詢結果中的第一個對象開始檢索
  • setMaxResults(int maxResults): 設定一次最多檢索出的對象的數(shù)目. 在默認情況下, Query 和 Criteria 接口檢索出查詢結果中所有的對象
   /**
     * HQL分頁查詢
     * 
     */
    @Test
    public void testPageQuery(){
        String HQL="from Employee";
        int pageNo=2;
        int pageSize=5;
        List<Employee> emps= session.createQuery(HQL)
                                   .setFirstResult((pageNo-1)*pageSize)
                                   .setMaxResults(pageSize)
                                   .list();
        System.out.println(emps);

    }

4.在映射文件中定義命名查詢語句
Hibernate 允許在映射文件中定義字符串形式的查詢語句.
元素用于定義一個 HQL 查詢語句, 它和 元素并列.
在程序中通過 Session 的 getNamedQuery() 方法獲取查詢語句對應的 Query 對象.
本例在Employee.hbm.xml映射文件中定義了如下:

<query name="salaryEmp">
      <![CDATA[   
       from Employee e where e.salary> :minSal and e.salary < :maxSal 
      ]]>
    </query>

之后就可以使用如下代碼來使用次查詢語句:

   /**
     * HQL命名查詢(HQL語句配置在hbm文件中的query標簽中,使用CDATA包裹)
     * 
     */
    @Test
    public void testNamedQuery(){
        Query query=session.getNamedQuery("salaryEmp");
        List<Employee> emps=query.setFloat("minSal", 2000)
                                  .setFloat("maxSal", 5000)
                                  .list();
        System.out.println(emps);
    }

5.HQL 左外連接:

  • LEFT JOIN 關鍵字表示左外連接查詢.
  • list() 方法返回的集合中存放的是對象數(shù)組類型
  • 根據(jù)配置文件來決定 Employee 集合的檢索策略(是否延遲加載)
  • 如果希望 list() 方法返回的集合中僅包含 Department 對象, 可以在HQL 查詢語句中使用 SELECT 關鍵字
   /**
     * HQL 左外連接
     */
    @Test
    public void testLeftJoin(){
        String hql="select distinct d from Department d left join d.emps";
        Query query=session.createQuery(hql);
        List<Department> depts=query.list();
        for (Department dept : depts) {
            System.out.println(dept.getName()+"-"+dept.getEmps().size());
        }
    }

綜上迫切左外連接和左外連接:

  • 如果在 HQL 中沒有顯式指定檢索策略, 將使用映射文件配置的檢索策略.
  • HQL 會忽略映射文件中設置的迫切左外連接檢索策略, 如果希望 HQL 采用迫切左外連接策略, 就必須在 HQL 查詢語句中顯式的指定它
  • 若在 HQL 代碼中顯式指定了檢索策略, 就會覆蓋映射文件中配置的檢索策略
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容