hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)

 

hibernate有五种检索方式,这儿用 单向的一对多的映射关系 例子,这儿有后三种的方式;

导航对象图检索方式: 根据已经加载的对象导航到其他对象

OID 检索方式: 按照对象的 OID 来检索对象

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

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

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

 

建立封装数据库中数据属性的封装类:n-1;

n的一端封装类:

package com.atguigu.hibernate.entities;

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;
    }

    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 + "]";
    }
    
}

 

1的一端封装的类:

package com.atguigu.hibernate.entities;

public class Employee {
    private Integer id;
    private String name;
    private float salary;
    private String email;
    
    private Department dept;

    public Employee() {
        super();
    }

    public Employee(String name, float salary, String email,
            Department dept) {
        super();
        this.name = name;
        this.salary = salary;
        this.email = email;
        this.dept = 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;
    }

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

 

在该包下自动生成对用的关系映射文件,只需进行一些修改;

单向的n-1映射关联关系,1的一端,关系映射文件;

<?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 2016-9-26 8:08:56 by Hibernate Tools 3.4.0.CR1 -->

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

    <class name="Employee" table="LL_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>
    
    <!-- 在映射文件中定义命名查询语句 ,书写的位置不在class范围内,注意书写的位置-->
        <query name="salaryemp"><![CDATA[from Employee e where e.salary >:minSal and e.salary <:maxSal]]></query>
</hibernate-mapping>

单向的n-1映射关联关系,n的一端,关系映射文件;

<?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 2016-9-26 8:08:56 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.atguigu.hibernate.entities">

    <class name="Department" table="LL_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="LL_EMPLOYEE" inverse="true" lazy="true">
            <key>
                <column name="DEPT_ID" />
            </key>
            <one-to-many class="Employee" />
        </set>
        
    </class>
</hibernate-mapping>

 

在src目录下建立hibernate的配置文件:

<?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 连接数据库的基本信息 -->
    <property name="connection.username">lxn123</property>
    <property name="connection.password">lxn123</property>
    <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
    <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl1</property>
    
    <!--  -->
    <!-- Hibernate 的基本配置 -->
    <!-- Hibernate 使用的数据库方言 ,是oracle书籍库的基本方言-->
    <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
    
    <!-- 运行时是否打印 SQL -->
    <property name="show_sql">true</property>
    
    <!-- 运行时是否格式化 SQL -->
    <property name="format_sql">true</property>
    
    <!-- 生成数据表的策略 -->
    <property name="hbm2ddl.auto">update</property>
    
    <!-- 设置 Hibernate 的事务隔离级别 -->
    <property name="connection.isolation">2</property>
    
    <!-- 删除对象后, 使其 OID 置为 null -->
    <property name="use_identifier_rollback">true</property>
    
    <!-- 配置 C3P0 数据源,不是开发 这儿就不配置了 -->
    
    
    <!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 -->
    <property name="hibernate.jdbc.fetch_size">100</property>
        
    <!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 -->
    <property name="jdbc.batch_size">30</property>
    
    <!-- 需要关联的 hibernate 映射文件 .hbm.xml -->
    <mapping resource="com/atguigu/hibernate/entities/Department.hbm.xml"/>
    <mapping resource="com/atguigu/hibernate/entities/Employee.hbm.xml"/>
    
    </session-factory>
</hibernate-configuration>

 

建立测试类,进行测试方法;

package com.atguigu.hibernate.test;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
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.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 com.atguigu.hibernate.entities.Department;
import com.atguigu.hibernate.entities.Employee;

public class HqlTest {
    
    private static SessionFactory sessionFactory;
    private static Session session;
    private static Transaction transaction;
    
    @Before
    public void init(){
        Configuration configuration=new Configuration().configure();
        ServiceRegistry serviceRegistry=
                    new ServiceRegistryBuilder()
                    .applySettings(configuration.getProperties())
                    .buildServiceRegistry();
        sessionFactory=configuration.buildSessionFactory(serviceRegistry);
        
        session=sessionFactory.openSession();
        transaction=session.beginTransaction();
    }
    
    @After
    public void destroy(){
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
    
    @Test
    //hql也可以进行曾删改的操作
    public void testHQLUpdate(){
        String hql = "DELETE FROM Department d WHERE d.id = :id";
        
        session.createQuery(hql).setInteger("id", 280)
                                .executeUpdate();
    }
    
    @Test
    //本地 SQL 检索
    public void testNativeSQL(){
        String sql = "INSERT INTO ll_department VALUES(?, ?)";
        Query query = session.createSQLQuery(sql);
        
        query.setInteger(0, 280)
             .setString(1, "ATGUIGU")
             .executeUpdate();
    }
    
    @Test
    //QBC检索, 添加排序,添加翻页方法
    public void testQBC4(){
        Criteria criteria = session.createCriteria(Employee.class);
        
        //1. 添加排序
        criteria.addOrder(Order.asc("salary"));
        criteria.addOrder(Order.desc("email"));
        List<Employee> empss=criteria.list();
        System.out.println(empss);
        
        //2. 添加翻页方法
        int pageSize = 5;
        int pageNo = 3;
        List<Employee> emps=criteria.setFirstResult((pageNo - 1) * pageSize)
                .setMaxResults(pageSize)
                .list();
        System.out.println(emps);
    }
    
    @Test
    //QBC检索,统计查询
    public void testQBC3(){
        Criteria criteria = session.createCriteria(Employee.class);
        
        //统计查询: 使用 Projection 来表示: 可以由 Projections 的静态方法得到
        criteria.setProjection(Projections.max("salary"));
        
        System.out.println(criteria.uniqueResult()); 
    }
    
    @Test
    //QBC检索,AND  OR
    public void testQBC2(){
        Criteria criteria = session.createCriteria(Employee.class);
        
        //1. AND: 使用 Conjunction 表示
        //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); 
        
        //2. OR
        Disjunction disjunction = Restrictions.disjunction();
        disjunction.add(Restrictions.ge("salary", 6000F));
        disjunction.add(Restrictions.isNull("email"));
        
        criteria.add(disjunction);
        criteria.add(conjunction);
        
        criteria.list();
        System.out.println(criteria);
    }
    
    @Test
    //QBC检索
    public void testQBC(){
        //1. 创建一个 Criteria 对象
        Criteria criteria = session.createCriteria(Employee.class);
        
        //2. 添加查询条件: 在 QBC 中查询条件使用 Criterion 来表示
        //Criterion 可以通过 Restrictions 的静态方法得到
        //eq,是等于,gt是大于
        criteria.add(Restrictions.eq("email", "SKUMAR"));
        criteria.add(Restrictions.gt("salary", 5000F));
        
        //3. 执行查询
        Employee employee = (Employee) criteria.uniqueResult();
        System.out.println(employee); 
    }
    
    @Test
    //内连接
    public void testinnerjoin(){
        String hql = "SELECT e FROM Employee e INNER JOIN e.dept";
        Query query = session.createQuery(hql);
        
        List<Employee> emps = query.list();
        emps=new ArrayList<>(new LinkedHashSet<>(emps));
        System.out.println(emps.size()); 
        
        for(Employee emp: emps){
            System.out.println(emp.getName() + ", " + emp.getDept().getName());
        }
    }
    
    @Test
    //迫切内连接
    public void testinnerjoinfetch(){

        String hql = "FROM Department d INNER JOIN FETCH d.emps";
        Query query = session.createQuery(hql);
        
        List<Department> depts = query.list();
        //取消重复的行
        depts = new ArrayList<>(new LinkedHashSet(depts));
        System.out.println(depts.size()); 
        
        for(Department dept: depts){
            System.out.println(dept.getName() + "-" + dept.getEmps().size());
        }
    }
    
    @Test
    //左外连接,DISTINCT取消重复的行
    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();
        System.out.println(depts.size());
        
        for(Department dept: depts){
            System.out.println(dept.getName() + ", " + dept.getEmps()); 
        }
        
//        List<Object []> result = query.list(); 
//        result = new ArrayList<>(new LinkedHashSet<>(result));,取消重复的行
//        System.out.println(result); 
//        
//        for(Object [] objs: result){
//            System.out.println(Arrays.asList(objs));
//        }
    }
    
    
    //迫切左外连接LEFT JOIN FETCH,DISTINCT是取消重复的行
    public void testLeftJoinFetch(){
        String hql="select distinct d from Department d left join fetch d.emps";
        Query query=session.createQuery(hql);
        
        List<Department> depts=query.list();
        
        //取消重复的行,set集合中没有重复的值
        depts=new ArrayList<>(new LinkedHashSet<>(depts));
        System.out.println(depts.size());
        
        for(Department dept:depts){
            System.out.println(dept.getName()+"--"+dept.getEmps());
        }
        
    }
    
    
    //报表查询,即在sql是分组查询,只查询部分属性
    public void testGroupBy(){
        String hql="select min(e.salary),max(e.salary) "
                + "from Employee e group by e.dept having min(salary)>:de";
        
        Query query=session.createQuery(hql).setFloat("de", 5000);
        
        //数组的形式
        List<Object []> result=query.list();
        for(Object [] emp:result){
            System.out.println(Arrays.asList(emp));
        }
    }
    
    //投影查询,即查询部分属性
    public void testFieldQuery2(){
        
        String hql="select new Employee(e.name,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.getName()+","+emp.getSalary()+","+emp.getEmail()+","+emp.getDept());
        }
    }
    
    @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 [] emps:result){
            System.out.println(Arrays.asList(emps));
        }
    }
    
    //在映射文件中定义命名查询语句方式的命名查询,在映射文件中要配置的。。。
    //此查询方法,只能查询到在此范围内的个数,不能查询到具体的属性值
    public void  testNamedQuery(){
        Query query =session.getNamedQuery("salaryemp");
        
        List<Employee> emps=
                query.setFloat("minSal", 5000)
                    .setFloat("maxSal", 10000)
                    .list();
        System.out.println(emps.size());
    }
    
    //分页查询,此查询只能查询到,对应的id
    @Test
    public void testPageQuery(){
        String hql="from Employee";
        Query query=session.createQuery(hql);
        
        //第三页
        int pageNo=3;
        //每页的大小为5
        int pageSize=5;
        
        /*
         * setFirstResult(int firstResult): 设定从哪一个对象开始检索, 
         * 参数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 
         * 默认情况下, Query 从查询结果中的第一个对象开始检索
         * 
         * setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. 
         * 在默认情况下, Query 和 Criteria 接口检索出查询结果中所有的对象
         * */
        List<Employee> emps=
                query.setFirstResult((pageNo-1)*pageSize)
                .setMaxResults(pageSize).list();
        System.out.println(emps);
    }
    
    //基于命名参数的查询
    //此查询方法,只能查询到在此范围内的个数,不能查询到具体的属性值
    public void testHQLNamedParameter(){
        //1. 创建 Query 对象
        //基于命名参数.
        String hql="from Employee e where e.salary > :sal and e.email like :ema";
        Query query = session.createQuery(hql);
        
        //2. 绑定参数。setFloat,setString,都为设置属性的类型
        query.setFloat("sal", 7000).setString("ema", "%A%");
        
        //3. 执行查询
        List<Employee> emp=query.list();
        System.out.println(emp.size());
    }
    
    //此查询方法,只能查询到在此范围内的个数,不能查询到具体的属性值
    public void testHql(){

        //1. 创建 Query 对象
        //基于位置的参数.hql是面向对象的,所以,书写表名时 为封装属性的类名;
        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, 5000).setString(1, "%A%").setEntity(2, dept);
        
        //3. 执行查询
        List<Employee> emp=query.list();
        System.out.println(emp.size());
    }
}

 

posted @ 2016-09-26 20:18  G-&-D  阅读(806)  评论(0编辑  收藏  举报