學習hibernate(八) -- HQL查詢語句

HQL語句java

HQL(Hibernate Query Language)提供更加豐富靈活、更爲強大的查詢能力。數據庫

  • 可設定WHERE數組

  • 可進行投影查詢session

  • 可分頁app

  • 可分組函數

  • 可作鏈接查詢測試

  • 有聚合函數fetch

  • 支持子查詢this

  • 可動態綁定參數.net

    先看一個HQL的基本用法,使用一對多多對一進行測試,Customer爲一的一端,Order爲多的一端,具體代碼,配置文件和數據庫數據以下:

<class name="cn.net.bysoft.model1.Customer" table="CUSTOMERS" batch-size="4">
        <id name="id" type="integer" column="ID">
            <!-- 指定主鍵的生成方式,native是使用數據庫本地的方式 -->
            <generator class="native"></generator>
        </id>
        <property name="name" type="string" column="NAME"></property>
        <!-- 一對多 -->
        <set name="orders" table="ORDERS" inverse="true" cascade="delete">
            <key column="CUSTOMER_ID"></key>
            <one-to-many class="cn.net.bysoft.model1.Order" />
        </set>
    </class>
<class name="cn.net.bysoft.model1.Order" table="ORDER_CUSTOMER">
        <id name="id" type="integer" column="ID">
            <!-- 指定主鍵的生成方式,native是使用數據庫本地的方式 -->
            <generator class="native"></generator>
        </id>
        <property name="name" type="string" column="NAME"></property>
        <!-- order.hbm.xml的多對一配置 -->
        <many-to-one name="customer" class="cn.net.bysoft.model1.Customer"
            column="CUSTOMER_ID" lazy="false" fetch="join">
        </many-to-one>
    </class>

    @Test
    public void testHql() {
        // 建立hql查詢對象
        // 使用佔位符表明參數
        String hql = "FROM Customer c WHERE c.id = ? OR c.name LIKE ? ORDER BY c.id DESC";
        Query query = session.createQuery(hql);

        // 設置參數的值
        query.setInteger(0, 1).setString(1, "%B%");
        List<Customer> customers = query.list();

        // 顯示結果
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }


    還能夠使用命名佔位符對WHERE條件的參數進行佔位:

@Test
    public void testHqlNameParam() {
        // 建立hql查詢對象
        // 使用命名錶明參數
        String hql = "FROM Customer c WHERE c.id = :id OR c.name LIKE :name ORDER BY c.name ASC";
        Query query = session.createQuery(hql);

        // 設置參數的值
        query.setInteger("id", 2).setString("name", "%C%");
        List<Customer> customers = query.list();

        // 顯示結果
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }

    也能夠使用實體做爲參數:

    @Test
    public void testHqlEntityParam() {
        // 建立hql查詢對象
        // 使用實體類做爲參數
        String hql = "FROM Order o WHERE o.customer = ?";
        Query query = session.createQuery(hql);

        // 設置參數的值
        Customer customer = new Customer();
        customer.setId(3);
        query.setEntity(0, customer);
        List<Order> orders = query.list();

        // 顯示結果
        for (Order order : orders) {
            System.out.println(order.getName());
        }
    }

    分頁查詢:

    @Test
    public void testHqlPageQuery() {
        // 建立hql查詢對象
        // 使用佔位符表明參數
        String hql = "FROM Customer c";
        Query query = session.createQuery(hql);

        // 當前頁
        int pageNum = 3;
        // 每頁行數
        int pageSize = 10;

        // 得到第一頁,也就是前十條
        List<Customer> customers = query
                .setFirstResult((pageNum - 1) * pageSize)
                .setMaxResults(pageSize).list();

        // 顯示結果
        int i = 1;
        for (Customer customer : customers) {
            System.out.println("第" + (i++) + " 條:" + customer.getName());
        }
    }

    hql查詢語句也能夠定義在配置文件中,方便部署後的修改。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.net.bysoft.model1.Customer" table="CUSTOMERS" batch-size="4">
        <id name="id" type="integer" column="ID">
            <!-- 指定主鍵的生成方式,native是使用數據庫本地的方式 -->
            <generator class="native"></generator>
        </id>
        <property name="name" type="string" column="NAME"></property>
        <!-- 一對多 -->
        <set name="orders" table="ORDERS" inverse="true" cascade="delete">
            <key column="CUSTOMER_ID"></key>
            <one-to-many class="cn.net.bysoft.model1.Order" />
        </set>
    </class>
    
    
    <!-- 查詢語句定義 -->
    <query name="FindCustomerByName">
        <![CDATA[
            FROM Customer c WHERE c.name = :name
        ]]>
    </query>
</hibernate-mapping>
    @Test
    public void testHqlBySetQuery() {
        // 從配置文件中得到查詢的hql語句,並建立query對象
        Query query = session.getNamedQuery("FindCustomerByName");
        // 賦值參數
        query.setString("name", "GG");
        List<Customer> customers = query.list();
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }

    若是不須要查詢全部的列,值查詢幾個字段,也就是投影查詢,查詢結果爲List<Object[]>,字段的值封裝在Object[]數組中:

@Test
    public void testHqlByProperty() {
        Query query = session
                .createQuery("SELECT c.id, c.name FROM Customer c");
        List<Object[]> customers = query.list();
        for (Object[] customer : customers) {
            System.out.println(Arrays.asList(customer));
        }
    }

    若是以爲放到Object[]中不方便,也能夠把投影放入對象中保存,前提是對象有支持投影的構造函數:

    @Test
    public void testHqlByPropertyEx() {
        Query query = session
                .createQuery("SELECT new Customer(c.id, c.name) FROM Customer c");
        List<Customer> customers = query.list();
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }
    
    public Customer(int id, String name) {
        super();
        Id = id;
        this.name = name;
    }

    能夠進行分組查詢統計:

    @Test
    public void testHqlByGroupBy() {
        // 使用分組,查詢出每一個用戶有多少個訂單
        String hql = "SELECT count(o.customer) FROM Order o GROUP BY o.customer";
        Query query = session.createQuery(hql);
        List<Integer> orders = query.list();

        // 顯示結果
        System.out.println(orders);
    }

    能夠使用迫切左外鏈接進行表與表的關聯,直接檢索出全部對象的數據,重複值能夠使用DISTINCT或者強轉HashSet解決:

@Test
    public void testHqlByLeftJoinFetch() {
        // 迫切左外鏈接
        // String hql =
        // "SELECT DISTINCT c FROM Customer c LEFT JOIN FETCH c.orders";
        String hql = "FROM Customer c LEFT JOIN FETCH c.orders";
        Query query = session.createQuery(hql);
        List<Customer> customers = query.list();

        customers = new ArrayList<Customer>(new LinkedHashSet<Customer>(
                customers));

        for (Customer customer : customers) {
            for (Order order : customer.getOrders()) {
                System.out.println(customer.getName() + ":" + order.getName());
            }
        }
    }

    能夠使用普通左外鏈接進行表與表的關聯,當使用到關聯的對象的數據時在發送SQL查詢語句,去重複值如上解決:

@Test
    public void testHqlByLeftJoin() {
        // 左外鏈接
        String hql = "SELECT DISTINCT c FROM Customer c LEFT JOIN c.orders";
        Query query = session.createQuery(hql);
        List<Customer> customers = query.list();

        // customers = new ArrayList<Customer>(new
        // LinkedHashSet<Customer>(customers));

        for (Customer customer : customers) {
            for (Order order : customer.getOrders()) {
                System.out.println(customer.getName() + ":" + order.getName());
            }
        }
    }

    另外還有迫切內連接,普通內連接等,用法如上。

    接着介紹一下QBC查詢方式,經過面向對象的方式建立查詢:

@Test
    public void testQBC() {
        // 建立QBC查詢
        Criteria criteria = session.createCriteria(Customer.class);
        // 添加查詢條件
        criteria.add(Restrictions.eq("name", "AA"));
        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(customer.getName());
    }

    使用AND鏈接查詢條件:

@Test
    public void testQBCAnd() {
        // 建立QBC查詢
        Criteria criteria = session.createCriteria(Customer.class);
        
        // 使用and鏈接查詢條件
        Conjunction conjunction = Restrictions.conjunction();
        conjunction.add(Restrictions.like("name", "B", MatchMode.ANYWHERE));
        conjunction.add(Restrictions.eq("id", 2));

        criteria.add(conjunction);
        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(customer.getName());
    }

    使用OR鏈接查詢條件:

@Test
    public void testQBCOr() {
        // 建立QBC查詢
        Criteria criteria = session.createCriteria(Customer.class);
        //    使用OR鏈接查詢條件
        Disjunction disjunction = Restrictions.disjunction();
        disjunction.add(Restrictions.like("name", "C", MatchMode.ANYWHERE));
        disjunction.add(Restrictions.eq("id", 1));

        criteria.add(disjunction);
        List<Customer> customers = criteria.list();
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }

    使用聚合函數:

@Test
    public void testQBCMax() {
        // 建立QBC查詢
        Criteria criteria = session.createCriteria(Customer.class);
        //    使用聚合函數
        criteria.setProjection(Projections.max("id"));

        System.out.println(criteria.uniqueResult());
    }

    使用分頁:

@Test
    public void testQBCByPageAndOrder() {
        // 建立QBC查詢
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.addOrder(org.hibernate.criterion.Order.desc("id"));
        
        // 使用分頁
        int pageNum = 2;
        int pageSize = 10;

        criteria.setFirstResult((pageNum - 1) * pageSize).setMaxResults(
                pageSize);

        List<Customer> customers = criteria.list();
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }

    最後,介紹一下使用本地SQL進行增刪改等操做:

@Test
    public void testQBCByPageAndOrder() {
        // 建立QBC查詢
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.addOrder(org.hibernate.criterion.Order.desc("id"));
        
        // 使用分頁
        int pageNum = 2;
        int pageSize = 10;

        criteria.setFirstResult((pageNum - 1) * pageSize).setMaxResults(
                pageSize);

        List<Customer> customers = criteria.list();
        for (Customer customer : customers) {
            System.out.println(customer.getName());
        }
    }

    以上就是hibernate的HQL、QBC和本地SQL查詢檢索。

相關文章
相關標籤/搜索