学习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查询检索。

相关文章
相关标签/搜索