Hibernate-HQL-QBC 检索-本地SQL 检索

HQL 检索方式: 使用面向对象的 HQL 查询语言
1:HQL 对比 SQL:
HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句. HQL查询语句中的主体是域模型中的类及类的属性
SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段. 
2:HQL查询步骤:
通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询语句. HQL 查询语句中可以包含命名参数
动态绑定参数
绑定参数:
Hibernate 的参数绑定机制依赖于 JDBC API 中的 PreparedStatement 的预定义 SQL 语句功能.
     HQL 的参数绑定由两种形式:
按参数名字绑定: 在 HQL 查询语句中定义命名参数, 命名参数以 “:” 开头.
按参数位置绑定: 在 HQL 查询语句中用 “?” 来定义参数位置
相关方法:
setEntity(): 把参数与一个持久化类绑定
setParameter(): 绑定任意类型的参数. 该方法的第三个参数显式指定 Hibernate 映射类型
调用 Query 相关方法执行查询语句. 
    (Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型)
3:HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:
在查询语句中设定各种查询条件
支持投影查询, 即仅检索出对象的部分属性
投影查询: 查询结果仅包含实体的部分属性. 通过 SELECT 关键字实现.
Query 的 list() 方法返回的集合中包含的是数组类型的元素, 每个对象数组代表查询结果的一条记录
可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录, 使程序代码能完全运用面向对象的语义来访问查询结果集. 
可以通过 DISTINCT 关键字来保证查询结果不会返回重复元素
支持分页查询
setFirstResult(int firstResult): 设定从哪一个对象开始检索, 参数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下, Query 从查询结果中的第一个对象开始检索
setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. 在默认情况下, Query 和 Criteria 接口检索出查询结果中所有的对象
支持连接查询
HQL (迫切)左外连接:
迫切左外连接:
LEFT JOIN FETCH 关键字表示迫切左外连接检索策略.
list() 方法返回的集合中存放实体对象的引用, 每个 Department 对象关联的 Employee  集合都被初始化, 存放所有关联的 Employee 的实体对象. 
查询结果中可能会包含重复元素, 可以通过一个 HashSet 来过滤重复元素
左外连接:
LEFT JOIN 关键字表示左外连接查询. 
list() 方法返回的集合中存放的是对象数组类型
根据配置文件来决定 Employee 集合的检索策略. 
如果希望 list() 方法返回的集合中仅包含 Department 对象, 可以在HQL 查询语句中使用 SELECT 关键字
迫切内连接:
INNER JOIN FETCH 关键字表示迫切内连接, 也可以省略 INNER 关键字
list() 方法返回的集合中存放 Department 对象的引用, 每个 Department 对象的 Employee 集合都被初始化, 存放所有关联的 Employee 对象
内连接:
INNER JOIN 关键字表示内连接, 也可以省略 INNER 关键字
list() 方法的集合中存放的每个元素对应查询结果的一条记录, 每个元素都是对象数组类型
如果希望 list() 方法的返回的集合仅包含 Department  对象, 可以在 HQL 查询语句中使用 SELECT 关键字
支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字
提供内置聚集函数, 如 sum(), min() 和 max()
支持子查询
支持动态绑定参数
能够调用 用户定义的 SQL 函数或标准的 SQL 函数
4:QBC 检索和本地 SQL 检索

QBC 查询就是通过使用 Hibernate 提供的 Query By Criteria API 来查询对象,这种 API 封装了 SQL 语句的动态拼装,对查询提供了更加面向对象的功能接口
本地SQL查询来完善HQL不能涵盖所有的查询特性

5:调测案例:

/*
 * 文件名:HibernateTest.java
 * 版权:Copyright by www.huawei.com
 * 描述:
 * 修改人:Cuigaochong
 * 修改时间:2015-10-22
 * 跟踪单号:
 * 修改单号:
 * 修改内容:
 */

package com.cgc.hibernate.test;

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.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.cgc.hibernate.entities.Department;
import com.cgc.hibernate.entities.Employee;

/**
 * <一句话功能简述> <功能详细描述>
 * 
 * @author 姓名 工号
 * @version [版本号, 2015-10-22]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class HibernateTest
{
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        Configuration configuration = new Configuration().configure();
        // 创建一个ServiceRegisttry对象:hibernate 4.x,新添加的对象,hibernate的任何配置和服务器都需要
        // 在该配置中注册后才能生效
        ServiceRegistry serviceRegistry =
            new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        
        session = sessionFactory.openSession();
        // 开启事物
        transaction = session.beginTransaction();
    }
    
    @After
    public void detory()
    {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
    
    @Test
    public void testSave()
    {
        // 创建Query对象
        // 基于位置参数
        String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept=? ORDER BY e.salary";
        Query query = session.createQuery(hql);
        // 绑定参数
        Department dept = new Department();
        dept.setId(80);
        query.setFloat(0, 6000).setString(1, "%A%").setEntity(2, dept);
        // 执行查询
        List<Employee> emps = query.list();
        System.out.println(emps.size());
    }
    
    @Test
    public void testHqlNameParameter()
    {
        // 创建Query对象
        // 基于命名参数
        String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";
        Query query = session.createQuery(hql);
        // 绑定参数
        // Query对象调用setXxx方法支持方法链的风格
        query.setFloat("sal", 6000).setString("email", "%A%");
        // 执行查询
        List<Employee> emps = query.list();
        System.out.println(emps.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 testNamedQuery()
    {
        Query query = session.getNamedQuery("salaryEmps");
        List<Employee> emps = query.setFloat("minSal", 1000).setFloat("maxSal", 5000).list();
        System.out.println(emps.size());
    }
    
    @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(60);
        List<Object[]> result = query.setEntity("dept", dept).list();
        System.out.println(result);
        
        for (Object[] objs : result)
        {
            System.out.println(Arrays.asList(objs));
        }
    }
    
    @Test
    public void testFieldQuery00()
    {
        String hql = "SELECT new Employee(e.email , e.salary,e.dept) FROM Employee e WHERE e.dept = :dept";
        Query query = session.createQuery(hql);
        Department dept = new Department();
        dept.setId(60);
        List<Employee> result = query.setEntity("dept", dept).list();
        System.out.println(result);
        
        for (Employee employee : result)
        {
            System.out.println(Arrays.asList(employee));
        }
    }
    
    @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));
        }
        
    }
    
    // 强制左外链接
    
    // 在表中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值。
    // 关键词 distinct用于返回唯一不同的值。
    @Test
    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();
        System.out.println(depts.size());
        for (Department dept : depts)
        {
            System.out.println(dept);
        }
    }
    
    // 左外链接
    @Test
    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().size());
        }
    }
    
    // 多对一
    // 不加fetch不会自动加载部门属性 在使用的时候在去查询
    @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 testQBC()
    {
        // 创建一个criteria对象
        Criteria criteria = session.createCriteria(Employee.class);
        // 添加查询条件:在QBC中查询条件使用Restrictions来表示
        // Restrictions可以通过静态的方法得到
        // 等于
        criteria.add(Restrictions.eq("email", "SKUMAR"));
        // 大于
        criteria.add(Restrictions.gt("salary", 5000F));
        // 执行查询
        Employee employee = (Employee)criteria.uniqueResult();
        System.out.println(employee);
    }
    
    @Test
    public void testQBC2()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        // 1:AND: 使用Conjunction表示
        // Conjunction本身就是一个Criteria对象,且其中还可添加Criteria
        Conjunction conjuntion = Restrictions.conjunction();
        conjuntion.add(Restrictions.like("name", "a", MatchMode.ANYWHERE));
        Department dept = new Department();
        dept.setId(80);
        conjuntion.add(Restrictions.eq("dept", dept));
        
        System.out.println(conjuntion);
        
        // 2:or 使用Disjunction表示
        Disjunction disjuntion = Restrictions.disjunction();
        disjuntion.add(Restrictions.like("name", "a", MatchMode.ANYWHERE));
        Department dept00 = new Department();
        dept00.setId(80);
        disjuntion.add(Restrictions.eq("dept", dept00));
        
        System.out.println(disjuntion);
        
    }
    
    @Test
    public void testQBS3()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        // 统计查询
        criteria.setProjection(Projections.max("salary"));
        System.out.println(criteria.uniqueResult());
    }
    
    @Test
    public void testQBC4()
    {
        Criteria criteria = session.createCriteria(Employee.class);
        // 添加排序
        criteria.addOrder(Order.asc("salary"));
        criteria.addOrder(Order.desc("email"));
        
        // 2添加翻页
        int pageSize = 5;
        int pageNo = 3;
        criteria.setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize).list();
        
    }
    
    /*
     * 执行效果: select
     * 
     * from ( select row_.*, rownum rownum_ from ( select this_.ID as ID1_1_0_, this_.NAME as NAME2_1_0_, this_.SALARY
     * as SALARY3_1_0_, this_.EMAIL as EMAIL4_1_0_, this_.DEPT_ID as DEPT_ID5_1_0_ from GG_EMPLOYEE this_ order by
     * this_.SALARY asc, this_.EMAIL desc ) row_ where rownum <= ? ) where rownum_ > ?
     */

    // 执行本地sql
    @Test
    public void testNativeSql()
    {
        String sql = "insert into gg_department values(?,?)";
        Query query = session.createSQLQuery(sql);
        query.setInteger(0, 281).setString(1, "Cui").executeUpdate();
    }
    
    // Department不是表名 是对象名
    @Test
    public void testHQLUpdate()
    {
        String hql = "DELETE FROM Department d WHERE d.id = :id";
        session.createQuery(hql).setInteger("id", 281).executeUpdate();
    }
    
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值