首页 > 代码库 > hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)

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

 

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