昆明java培训
达内昆明广州春城路

18487146383

热门课程

Hibernate:HQL检索方式

  • 时间:2016-10-24
  • 发布:昆明Java培训
  • 来源:达内新闻

昆明Java培训机构的老师这一期给大家讲Hibernate的HQL检索方式。

一、HQL检索方式

以双向的一对多来测试HQL检索方式。以Department和Employee为例。

建表语句:

CREATE TABLE department

(

dept_id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,

dept_name VARCHAR(50)

);

CREATE INDEX FK_8hf3vewo7w3v9doungcc51wwy ON department (dept_id);

CREATE TABLE employee

(

emp_id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,

emp_name VARCHAR(50),

salary FLOAT,

dept_id_fk INT(11),

CONSTRAINT FK_miun1wlqp4ujpsgfshyfi7g9j FOREIGN KEY (dept_id_fk) REFERENCES department (dept_id)

);

CREATE INDEX FK_miun1wlqp4ujpsgfshyfi7g9j ON employee (dept_id_fk);

对应的实体和hbm文件

public class Department {

private Integer deptId;

private String deptName;

private Set<Employee> emps = new HashSet<>();

}   

public class Employee {

private Integer empId;

private String empName;

private Float salary;

private Department dept;

}

<hibernate-mapping>

<class ame="com.solverpeng.hql.Department" table="department" schema="hibernate">

<id name="deptId" column="dept_id">

<generator class="native"/>

</id>

<property name="deptName" column="dept_name"/>

<set name="emps" inverse="true">

<key>

<column ame="dept_id_fk"/>

</key>

<one-to-many ot-found="ignore" class="com.solverpeng.hql.Employee"/>

</set>

</class>

</hibernate-mapping>

<hibernate-mapping>

<class ame="com.solverpeng.hql.Employee" table="employee" schema="hibernate">

<id name="empId" column="emp_id">

<generator class="native"/>

</id>

<property name="empName" column="emp_name"/>

<property name="salary" column="salary"/>

<many-to-one name="dept" class="com.solverpeng.hql.Department">

<column ame="dept_id_fk"/>

</many-to-one>

</class>

<query ame="findAllEmployees">

<![CDATA[

from Employee

]]>

</query>

</hibernate-mapping>

1.在查询语句中设定各种查询条件

@Test

public void testHql(){

Department dept = new Department();

dept.setDeptId(7);

List<Employee> list = session.createQuery("FROM Employee e where e.empName like ? and e.empId > ? and dept = ? order by e.empId " +

"desc ")

.setString(0, "%b%").setInteger(1, 3).setEntity(2, dept).list();

for(Employee employee : list) {

System.out.println(employee);

}

}

说明:

(1)通过Session的createQuery(hql)方法创建一个Query对象,hql支持动态绑定参数。调用Query的相关方法执行查询。

(2)Query接口支持链式操作,它的setXxx()方法返回自身实例。

(3)方法setEntity(obj),obj只需要绑定一个id就可以。

(4)支持order by排序。

(5)参数的位置从0开始。

@Test

public void testHqlNamed() {

List<Employee> list = session.createQuery("from Employee e where e.empName like :name and e.empId > :id and e.dept = ?")

.setString("name", "%a%").setInteger("id", 1).list();

for(Employee employee : list) {

System.out.println(employee);

}

}

说明:

(1)支持按照参数名字查询,定义的参数名以":"开头。

2.查询对象的部分属性(查询结果仅包含实体的部分属性)

@Test

public void testPropertyQuery() {

Department dept = new Department();

dept.setDeptId(7);

List<Object[]> list = session.createQuery("select empName, empId from Employee where dept = ?").setEntity(0, dept).list();

for(Object[] objects : list) {

System.out.println(Arrays.asList(objects));

}

}

说明:

(1)这种情况下查询出来的是一个Object[]数组类型。

@Test

public void testPropertyQuery2() {

Department dept = new Department();

dept.setDeptId(7);

List<Employee> list = session.createQuery("select new Employee (empId, empName) from Employee where dept = ?").setEntity(0, dept)

.list();

for(Employee employee : list) {

System.out.println(employee);

}

}

(1)查询出来的是Employee类型

(2)需要在Employee实体类中定义相应的构造器,注意顺序。同时添加一个无参的构造器。

(3)可以通过Distinct关键字来去重。

3.分页查询

@Test

public void testHqlPage() {

int pageNo = 2;

int pageSize = 3;

List<Employee> list = session.createQuery("from Employee").setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize).list();

for(Employee employee : list) {

System.out.println(employee);

}

}

(1)setFirstResult(int firstResult):设定从哪一个对象开始检索。

(2)setMaxResults(int maxResult) :设定每次检索多少条记录。

4.命名查询(很少用到)

@Test

public void testNamedQuery() {

int pageNo = 3;

int pageSize = 5;

List<Employee> employees = session.getNamedQuery("findAllEmployees").setFirstResult((pageNo - 1) * pageSize).setMaxResults(

pageSize).list();

for(Employee employee : employees) {

System.out.println(employee);

}

}

说明:

(1)其中findAllEmployees定义在了Employee.hbm.xml文件中,用<query>元素来定义,和class节点并列。

(2)通过Session的getNamedQuery()方法获取对应的Query对象。

5.聚集函数和分组查询

@Test

public void testFunction() {

List<Object[]> salary =

session.createQuery("select dept.deptName, min(salary), max(salary) from Employee group by dept HAVING min(salary) > :salary")

.setFloat("salary", 4000).list();

for(Object[] objects : salary) {

System.out.println(Arrays.asList(objects));

}

}

说明:

(1)通过GROUP BY进行分组,通过HAVING对分组数据设定约束条件。

(2)可以调用的聚集函数:count()、min()、max()、sum()、avg()

6.迫切左外链接和左外链接

(1)迫切左外链接

@Test

public void testHqlFetch() {

List list = session.createQuery("from Department d left join fetch d.emps").list();

}

打印SQL:

Hibernate:

select

department0_.dept_id as dept1_0_0_,

emps1_.emp_id as emp1_1_1_,

department0_.dept_name as dept2_0_0_,

emps1_.emp_name as emp2_1_1_,

emps1_.salary as salary3_1_1_,

emps1_.dept_id_fk as dept4_1_1_,

emps1_.dept_id_fk as dept4_0_0__,

emps1_.emp_id as emp1_1_0__

from

hibernate.department department0_

left outer join

hibernate.employee emps1_

on department0_.dept_id=emps1_.dept_id_fk

说明:

同时查询了Employee对象

list()方法返回的集合存放的实体对象的引用,每个Department关联的Employee集合都被初始化。

可以通过distinct关键字去重,也可以通过一个HashSet()去重(new ArrayList<>(new LinkedHashSet(depts)))。

此种情况下,会忽略配置文件中检索策略。

(2)左外链接

@Test

public void testHqlLeftJoin2() {

List<Object[]> list = session.createQuery("from Department d left join d.emps").list();

for(Object[] objects : list) {

System.out.println(Arrays.asList(objects));

}

}

Hibernate:

select

department0_.dept_id as dept1_0_0_,

emps1_.emp_id as emp1_1_1_,

department0_.dept_name as dept2_0_0_,

emps1_.emp_name as emp2_1_1_,

emps1_.salary as salary3_1_1_,

emps1_.dept_id_fk as dept4_1_1_

from

hibernate.department department0_

left outer join

hibernate.employee emps1_

on department0_.dept_id=emps1_.dept_id_fk

说明:

list()方法返回的集合中存放的是对象数组类型。

根据配置文件来决定Employee集合的初始化时机。

7.迫切内连接和内连接

(1)迫切内连接(inner join fetch),与迫切左外链接类似,查询的时候同时将关联的另一端的对象进行了初始化。

(2)内连接(inner join),与左外链接类似,查询的时候是根据配置文件中的检索策略来决定另一端初始化的时机。

昆明Java培训机构的老师给大家做个小结

(1)如果在HQL中没有显式的指定检索策略,则使用配置文件中的检索策略。

(2)HQL会忽略配置文件中设置的迫切左外链接检索策略,若想HQL采用迫切左外链接策略,就必须在HQL语句中显式的指定它。

上一篇:java中借助commons-fileupload实现文件上传
下一篇:Hibernate:QBC检索方式

上java培训有用吗?怎么衡量?【达内培训】

昆明java培训机构怎么选?昆明达内java培训怎么样?

学Java自学还是达内培训机构好?

0基础学java垃圾代码回收站【达内编程培训】

选择城市和中心
贵州省

广西省

海南省

台湾