概述
HQL 检索方式
•HQL 检索方式包括以下步骤:
•Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型
•HQL vs SQL:
•绑定参数:
–HQL 的参数绑定由两种形式:
•HQL 采用 ORDER BY 关键字对查询结果排序
public void testHQL(){
//1. 创建 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); //2. 绑定参数
//Query 对象调用 setXxx 方法支持方法链的编程风格.
Department dept = new Department();
dept.setId(80);
query.setFloat(0, 6000)
.setString(1, "%A%")
.setEntity(2, dept); //3. 执行查询
List<Employee> emps = query.list();
System.out.println(emps.size());
}
testHQL1
public void testHQLNamedParameter(){
//1. 创建 Query 对象
//基于命名参数.
String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";
Query query = session.createQuery(hql); //2. 绑定参数
query.setFloat("sal", 7000)
.setString("email", "%A%"); //3. 执行查询
List<Employee> emps = query.list();
System.out.println(emps.size());
}
testHQL2
•分页查询:
public void testPageQuery(){
String hql = "FROM Employee";
Query query = session.createQuery(hql); int pageNo = 22;
int pageSize = 5; List<Employee> emps =query.setFirstResult((pageNo - 1) * pageSize)
.setMaxResults(pageSize)
.list();
System.out.println(emps);
}
testPageQuery
•在映射文件中定义命名查询语句
–在程序中通过 Session 的 getNamedQuery() 方法获取查询语句对应的 Query 对象.
<query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal]]></query>
public void testNamedQuery(){
Query query = session.getNamedQuery("salaryEmps"); List<Employee> emps = query.setFloat("minSal", 5000)
.setFloat("maxSal", 10000)
.list(); System.out.println(emps.size());
}
testNamedQuery
投影查询
•投影查询: 查询结果仅包含实体的部分属性. 通过 SELECT 关键字实现.
•Query 的 list() 方法返回的集合中包含的是数组类型的元素, 每个对象数组代表查询结果的一条记录
•可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录, 使程序代码能完全运用面向对象的语义来访问查询结果集.
•可以通过 DISTINCT 关键字来保证查询结果不会返回重复元素
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 [] objs: result){
System.out.println(Arrays.asList(objs));
}
}
testFieldQuery
public void testFieldQuery2(){
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(80);
List<Employee> result = query.setEntity("dept", dept)
.list();
for(Employee emp: result){
System.out.println(emp.getId() + ", " + emp.getEmail()
+ ", " + emp.getSalary() + ", " + emp.getDept());
}
}
testFieldQuery2
报表查询
•报表查询用于对数据分组和统计, 与 SQL 一样, HQL 利用 GROUP BY 关键字对数据分组, 用 HAVING 关键字对分组数据设定约束条件.
•在 HQL 查询语句中可以调用以下聚集函数
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", 8000); List<Object []> result = query.list();
for(Object [] objs: result){
System.out.println(Arrays.asList(objs));
}
}
testGroupBy
HQL (迫切)左外连接
•迫切左外连接:
•左外连接:
public void testLeftJoinFetch(){
// String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN FETCH d.emps";
String hql = "FROM Department d LEFT 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());
}
}
testLeftJoinFetch
HQL (迫切)内连接
•迫切内连接:
•内连接:
关联级别运行时的检索策略
•如果在 HQL 中没有显式指定检索策略, 将使用映射文件配置的检索策略.
•HQL 会忽略映射文件中设置的迫切左外连接检索策略, 如果希望 HQL 采用迫切左外连接策略, 就必须在 HQL 查询语句中显式的指定它
QBC 检索和本地 SQL 检索
•QBC 查询就是通过使用 Hibernate 提供的 Query By Criteria API 来查询对象,这种 API 封装了 SQL 语句的动态拼装,对查询提供了更加面向对象的功能接口
•本地SQL查询来完善HQL不能涵盖所有的查询特性
public void testQBC(){
//1. 创建一个 Criteria 对象
Criteria criteria = session.createCriteria(Employee.class); //2. 添加查询条件: 在 QBC 中查询条件使用 Criterion 来表示
//Criterion 可以通过 Restrictions 的静态方法得到
criteria.add(Restrictions.eq("email", "SKUMAR"));
criteria.add(Restrictions.gt("salary", 5000F)); //3. 执行查询
Employee employee = (Employee) criteria.uniqueResult();
System.out.println(employee);
}
testQBC1
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();
}
testQBC2
public void testQBC3(){
Criteria criteria = session.createCriteria(Employee.class); //统计查询: 使用 Projection 来表示: 可以由 Projections 的静态方法得到
criteria.setProjection(Projections.max("salary")); System.out.println(criteria.uniqueResult());
}
testQBC3
public void testQBC4(){
Criteria criteria = session.createCriteria(Employee.class); //1. 添加排序
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();
}
testQBC4
public void testNativeSQL(){
String sql = "INSERT INTO gg_department VALUES(?, ?)";
Query query = session.createSQLQuery(sql); query.setInteger(0, 280)
.setString(1, "ATGUIGU")
.executeUpdate();
}
testNativeSQL