HIBERNATE知识复习记录4-HQL和QBC

Posted liunianfeiyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HIBERNATE知识复习记录4-HQL和QBC相关的知识,希望对你有一定的参考价值。

  Hibernate中共提供了三种检索方式:HQL(Hibernate Query Language)、QBC、QBE(Query By Example)。

  HQL 是Hibernate Query Language的简写,即hibernate查询语言:HQL采用面向对象的查询方式。

  QBC(Query By Criteria) API提供了检索对象的另一种方式,它主要由Criteria接口、Criterion接口和Expresson类组成,它支持在运行时动态生成查询语句。

  HQL 查询包括以下步骤:

  1. 获取Hibernate Session对象。
  2. 编写HQL语句
  3. 以HQL语句作为参数,调用Session的createQuery方法创建查询对象。
  4. 如果HQL语句包含参数,则调用Query的setXxx方法为参数赋值。
  5. 调用Query对象的list()或uniqueResult()方法返回查询结果列表(持久化实体集)
  QBC检索步骤:
  1.调用Session的createCriteria()方法创建一个Criteria对象。
  2.设定查询条件。Restrictions类提供了一系列用于设定查询条件的静态方法
  这些静态方法都返回Criterion实例,每个Criterion实例代表一个查询条件。
  Criteria的add()方法用于加入查询条件。
  3.调用Criteria的list()方法执行查询语句。该方法返回List类型的查询结果,在
  List集合中存放了符合查询条件的持久化对象。
 
  下面列出我学习的代码。
  Department类
package oracle.hqlqbc;

import java.util.HashSet;
import java.util.Set;

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

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Department [id=");
        builder.append(id);
        builder.append(", name=");
        builder.append(name);
        builder.append(", empsSize=");
        builder.append(emps.size());
        builder.append("]");
        return builder.toString();
    }

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

    public Set<Employee> getEmps() {
        return emps;
    }

    public void setEmps(Set<Employee> emps) {
        this.emps = emps;
    }
}

  Employee类

package oracle.hqlqbc;

public class Employee {
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Employee [id=");
        builder.append(id);
        builder.append(", name=");
        builder.append(name);
        builder.append(", salary=");
        builder.append(salary);
        builder.append(", email=");
        builder.append(email);
        builder.append(", deptId=");
        builder.append(dept.getId());
        builder.append("]");
        return builder.toString();
    }

    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() {
    }
}

  Department.hbm.xml

<?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 2017-7-29 2:43:46 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="oracle.test">
    <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>

  Employee.hbm.xml

<?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 2017-7-29 2:43:46 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="oracle.test">
    <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" fetch="join"><!-- join select subselect-->
            <column name="DEPT_ID" />
        </many-to-one>
    </class>
    
    <query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal]]></query>
</hibernate-mapping>

  具体用法的例子:

package oracle.hqlqbc;

import java.util.Arrays;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import oracle.hqlqbc.Department;
import oracle.hqlqbc.Employee;

public class HibernateTest {
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        System.out.println("init");

        // 1. 创建一个SessionFactory对象
        sessionFactory = null;
        Configuration configuration = new Configuration().configure();
        
        // before 4.0
//        sessionFactory = configuration.buildSessionFactory();
        
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                                      .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        // 2. 创建一个Session 对象
        session = sessionFactory.openSession();
        
        // 3. 开启事务
        transaction = session.beginTransaction();
        
    }
    
    @After
    public void destory()
    {
        System.out.println("destory");
        // 5. 提交事务
        transaction.commit();
        
        // 6. 关闭Session
        session.close();
        
        // 7. 关闭SesssionFactory
        sessionFactory.close();
    }
    
    @Test
    public void testNamedParameter()
    {
        String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";
        Query query = session.createQuery(hql);
        
        // 可以用命名参数
        query.setFloat("sal", 7000)
            .setString("email", "%A%");
        
        List<Employee> emps = query.list();
        System.out.println(emps.size());
    }
    
    @Test
    public void createTable()
    {
        
    }
    
    @Test
    public void testHQL()
    {
        // 1. 创建Query对象: 可以加 ORDER BY
        String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND 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%");
        // 可用用实体
        query.setEntity(2, dept);
        
        // 3. 执行查询
        List<Employee> employees = query.list();
        System.out.println(employees.size());
    }
    
    /*
     * 分页查询
     */
    @Test
    public void testPageQuery()
    {
        String hql = "FROM Employee";
        Query query = session.createQuery(hql);
        
        int pageNo = 3;
        int pageSize = 5;
        
        List<Employee> emps = query.setFirstResult((pageNo - 1)* pageSize)
                                .setMaxResults(pageSize).list();
        System.out.println(emps);
    }
    
    /*
     * 命名查询
     */
    @Test
    public void namedQuery()
    {
        Query query = session.getNamedQuery("salaryEmps");
        List<Employee> emps = query.setFloat("minSal", 5000)
                                .setFloat("maxSal", 10000)
                                .list();
        System.out.println(emps.size());
    }
    
    /*
     * 投影查询1: 操作数组
     */
    @Test
    public void testPropertyQuery()
    {
        String hql = "SELECT e.email, e.salary 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));
        }
    }
    
    /*
     * 投影查询2: 操作entity:使用构造器
     */
    @Test
    public void testPropertyQuery2()
    {
        String hql = "SELECT new Employee(e.salary, e.email, 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.getId() + ", " + emp.getEmail() + ", " + emp.getSalary() + ", " + emp.getDept());
        }

    }
    
    /*
     * 报表查询: 可以使用聚合函数
     */
    @Test
    public void testGroupBy()
    {
        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));
        }
    }
    
    /*
     * HQL 会忽略配置文件中的fetch=join的设置,如果想用,就在代码中直接写
     * 迫切左外连接:返回department,注意去重
     */
    @Test
    public void testLeftJoinFetch()
    {
        String hql = "SELECT DISTINCT d FROM Department d INNER JOIN FETCH d.emps";
        Query query = session.createQuery(hql);
        
        // 集合去重
//        new ArrayList<>(new HashSet<>(Collection c));
        
        List<Department> depts = query.list();
        System.out.println(depts.size());
        
        for(Department dept: depts)
        {
            System.out.println(dept.getName() + ", " + dept.getEmps().size());
        }
    }
    
    /*
     * 默认返回对象数组,注意去重,
     */
    @Test
    public void testLeftJoin()
    {
        // 这样返回的Employee未被初始化
        String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN d.emps";
        Query query = session.createQuery(hql);
        
        /*List<Object[]> result = query.list();
        System.out.println(result);
        
        for(Object[] objs: result)
        {
            System.out.println(Arrays.asList(objs));
        }*/
        
        List<Department> depts = query.list();
        System.out.println(depts.size());
        for(Department dept: depts)
        {
            System.out.println(dept.getName());
        }
    }
    
    @Test
    public void testLeftJoinFetch2()
    {
        String hql = "SELECT e FROM Employee e INNER JOIN FETCH e.dept";
        Query query = session.createQuery(hql);
        
        List<Employee> emps = query.list();
        System.out.println(emps.size());
        
        for(Employee emp: emps)
        {
            System.out.println(emp.getName() + ", " + emp.getDept().getName());
        }
    }
    
    @Test
    public void testQBCQuery()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        criteria.add(Restrictions.eq("email", "SKUMAR"));
        criteria.add(Restrictions.gt("salary", 5000f));
        Employee employee = (Employee) criteria.uniqueResult();
        System.out.println(employee);
    }
    
    @Test
    public void testQBCQuery2()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        // 1. AND: 使用Conjunction表示,本身就是一个Criterion对象
        // 且其中还可以添加Criterion对象
        Conjunction conjunction = Restrictions.conjunction();
        conjunction.add(Restrictions.like("name", "a", MatchMode.ANYWHERE));
        
        Department dept = new Department();
        dept.setId(80);
        conjunction.add(Restrictions.eq("dept", dept));
        
        System.out.println(conjunction);
        
        // or
        Disjunction disjunction = Restrictions.disjunction();
        disjunction.add(Restrictions.ge("salary", 6000));
        disjunction.add(Restrictions.isNotNull("email"));
        criteria.add(conjunction);
        criteria.add(disjunction);
        
        criteria.list();
    }
    
    @Test
    public void testQBCQuery3()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        // 统计查询
        criteria.setProjection(Projections.max("salary"));
        
        System.out.println(criteria.uniqueResult());
    }
    
    @Test
    public void testQBCQuery4()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        criteria.addOrder(Order.asc("salary"));
        criteria.addOrder(Order.desc("email"));
        
        int pageSize = 5;
        int pageNo = 3;
        criteria.setFirstResult((pageNo - 1) * pageSize)
            .setMaxResults(pageSize).list();
    }
    
    @Test
    public void testNativeSQL()
    {
        String sql = "INSERT INTO department VALUES(?, ?)";
        Query query = session.createSQLQuery(sql);
        query.setInteger(0, 280)
             .setString(1, "ATGUIGU")
             .executeUpdate();
    }
    
    @Test
    public void testHQLUpdate()
    {
        String hql = "DELETE FROM Department d where d.id = :id";
        session.createQuery(hql).setInteger("id", 280).executeUpdate();
    }
}

  好了,例子都在上面,自己也复习了一遍,有了一个初步的印象,本文仅供入门了解,更深入的内容查看相关文章学习。


以上是关于HIBERNATE知识复习记录4-HQL和QBC的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 查询方式

Hibernate(十五):QBC检索和本地SQL检索

[原创]java WEB学习笔记92:Hibernate学习之路-- -QBC 检索和本地 SQL 检索:基本的QBC 查询,带 AND 和 OR 的QBC,统计查询,排序,分页

Hibernate 4:HQL 和继承 - 获取集合和 javassist

Hibernate QBC 分页

Hibernate_13_QBC查询