Hibernate查询
Hibernate支持3种查询方式,分别是HQL查询,Criteria查询,原生SQL查询
一.HQL查询
(一)什么是HQL
1.HQL:hibernate query language (Hibernate查询语言)
2. 语法和SQL很像,但是它是面向对象的查询语言,不是面向数据库
3. 除了Java类和属性的名称外,hql语句对大小写并不敏感
4. hql里面查询的是实体对象,所以写的是实体类的类名和属性名,严格区分大小写
5. HQL语句查询的是实体类的名称,不是数据库的表
6. HQL语句中的类名和属性名严格区分大小写
执行HQL语句的步骤
- 获取Session对象
- 编写HQL语句
- 创建Query对象
- 执行查询,得到查询结果
list()方法查询
//查询部门所有列表
public class App {
public static void main(String[] args) {
// 1.读取hibernate.cfg.xml配置文件
Configuration configuration = new Configuration().configure();
// 2.创建一个会话工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.打开一个会话
Session session = sessionFactory.openSession();
// 4.查询数据
//定义HQL语句
String hql = "from Department"; //查询的是类名称,不是表名
//创建Query对象
Query query = session.createQuery(hql);
//执行查询,得到结果集
List<Department> list = query.list();
//循环遍历
for (Department department : list) {
System.out.println(department);
}
// 5.关闭session
session.close();
}
}
iterate()方法查询
//查询部门所有列表
public class TestIterator {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//查询数据
String hql = "from Department";
Query query = session.createQuery(hql);
//执行查询,得到结果集(会发出1+N条SQL语句)
Iterator<Department> itor = query.iterate();
while (itor.hasNext()) {
//获取部门对象
Department department = itor.next();
System.out.println(department);
}
transaction.commit();
session.close();
}
}
list()方法和iterate()方法的区别:
- list()方法不会发出1+n条SQL语句 (list用的比较多)
- iterate()方法会发出1+n条SQL语句,在有缓存的基础上性能较好
HQL语句参数绑定
添加员工类Employee和员工映射文件
在resources下创建mapper包并在Employee.hbm.xml内配置
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
class标签:用于关联实体类,通过name属性指定实体类
name属性:关联实体类的路径
table属性:实体类关联的表名称
-->
<class name="com.hbrj.dao.Employee" table="employee" >
<!-- id标签配置主键字段-->
<!-- name属性:填写该实体类的属性名称(严格区分大小写) -->
<!-- column属性:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省
略 -->
<!-- type属性:填写该属性的数据类型 -->
<id name="empNo" column="empNo" type="java.lang.Integer">
<!-- 配置主键生成策略 -->
<!-- assigned:主键由程序提供(非自增)-->
<!-- <generator class="assigned"/>-->
<generator class="increment"></generator>
</id>
<!-- property标签配置普通列名 -->
<property name="empName" type="java.lang.String" column="empName"/>
<property name="job" type="java.lang.String" column="job" />
<property name="salary" type="java.lang.Double" column="salary"/>
<property name="deptNo" type="java.lang.Integer" column="deptNo" />
<property name="hireDate" type="java.util.Date" column="hireDate"/>
</class>
</hibernate-mapping>
在hibernate.cfg.xml内加载映射文件
在HQL语句中,给参数绑定数据可以使用以下2种方法,分别是:
- 按参数位置绑定
- 按参数名称绑定
高版本HQL参数绑定
- 观察HQL语句中的占位符?1,?2,其中?1是HQL语句中的第1个占位符
- 参数下标从1开始
/**
* 查询某个部门下的员工信息
*/
public class QueryEmployee {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//查询数据,根据参数位置赋值,进行查询
//定义HQL语句 HQL语句中的占位符?1,?2,其中?1是HQL语句中的第1个占位符
String hql = "from Employee where deptNo=?1 and empName like ?2";
Query query = session.createQuery(hql);
query.setParameter(1, 1);
query.setParameter(2, "%a%");
List<Employee> list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
session.close();
}
}
按参数名称绑定
HQL语句中可以使用 :参数名称 的方式进行传参,其中参数名称自定义
public class QueryEmployee2 {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//查询,根据参数名称进行复制 HQL语句中使用 :参数名称 的方式进行传参,其中参数名称自定义
String hql = "from Employee where empName like :empName and salary >=:salary";
Query query = session.createQuery(hql);
query.setParameter("empName", "%a%");
query.setParameter("salary", 6000.0);
List<Employee> list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
session.close();
}
}
Hibernate中的动态条件查询
-
setXXX(): 针对具体数据类型
- setXXX(int position, XXX value)
- setXXX(String name, XXX value)
-
setParamenter(): 任意类型参数
- setParameter( int position, Object value)
- setParameter( String name, Object value)
-
setProperties(): 专为命名参数定制
根据条件动态查询员工数据
1.根据职位查询,如:job=“Java工程师”
2.根据薪资查询,如:salary>=4000
3.入职时间 2018年1月1日 到 2020年1月1日
注意:条件个数不确定
说先自定义一个查询条件类(EmployeeVo)继承Employee
生成get和set方法
在hbrj下创建一个util包DateUtil类
用于转换时间日期
public static Date parseDate(String str) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
return format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
开始写测试类
/**
* 根据条件动态查询员工数据
* 1.根据职位查询,如:job="Java工程师"
* 2.根据薪资查询,如:salary>=4000
* 3.入职时间 2018年1月1日 到 2020年1月1日
*/
public class QueryEmployee3 {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
StringBuilder hql = new StringBuilder("from Employee where 1=1 ");
//动态条件查询
//定义一个查询条件的类对象
EmployeeVo employeeVo = new EmployeeVo();
employeeVo.setJob("%员%");
employeeVo.setSalary(5500.0);
employeeVo.setStartDate(DateUtil.parseDate("2023-3-2 00:00:00"));
employeeVo.setEndDate(DateUtil.parseDate("2023-3-9 00:00:00"));
//EmployeeVo实体类中的成员变量名必须跟参数名称一致。
if (employeeVo.getJob() != null) { //判断职位
hql.append("and job like :job "); //参数名称必须与实体类的属性名相同
}
if (employeeVo.getSalary() != null) { //判断薪资
hql.append("and salary >=:salary ");
}
if (employeeVo.getEmpName() != null) { //判断名字
hql.append("and empName like :empName ");
}
if (employeeVo.getStartDate() != null) { //判断开始日期
hql.append("and hireDate >=:startDate ");
}
if (employeeVo.getEndDate() != null) { //判断结束日期
hql.append("and hireDate <=:endDate");
}
Query query = session.createQuery(hql.toString());
System.out.println(hql);
//setProperties用来给参数赋值
query.setProperties(employeeVo);
List<Employee> list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
session.close();
}
}
UniqueResult()唯一结果
uniqueResult()方法只能返回唯一结果,返回多行记录会报错
public class TestUniqueRestult {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//查询员工数量
String hql = "from Employee where empNo=3";
Query query = session.createQuery(hql);
//uniqueResult必须保证查询结果只有一条记录 uniqueResult()方法只能返回唯一结果,返回多行记录会报错
Object department = query.uniqueResult();
System.out.println(department);
session.close();
}
}
分页查询
方法
uniqueResult() : 获取唯一对象
setFirstResult() : 设置从第几条开始
setMaxResults() : 设置读取最大记录数
public class QueryPage {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
int pageSize = 3;//每页显示的条数
int pageNo = 2;//从第几页开始
String hql = "from Employee order by empNo asc";
Query query = session.createQuery(hql);
//设置分页信息
query.setFirstResult((pageNo - 1) * pageSize);//从第几条开始,参数值为索引值
query.setMaxResults(pageNo);//每页显示的条数
List<Employee> list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
session.close();
}
}
投影查询
投影查询是查询一个持久化类的一个或多个属性值,或者是通过表达式或聚合函数得到的值
投影查询需要使用HQL的select子句
查询结果的封装主要分三种情况
- 封装成Objec对象(返回单列)
- 封装成Object数组(返回多列)
- 通过构造方法封装成对象
封装成Objec对象------ 返回单列对象
//查询员工姓名
public class TestSelect {
public static void main(String[] args) {
// 1.读取hibernate.cfg.xml配置文件
Configuration configuration = new Configuration().configure();
// 2.创建一个会话工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.打开一个会话
Session session = sessionFactory.openSession();
String hql = "select empName from Employee";
Query query = session.createQuery(hql);
List<Object> list = query.list();
for (Object employee : list) {
System.out.println(employee);
}
// 关闭session
session.close();
}
}
封装成Object数组----返回多列对象
//查询员工工号、姓名
ublic class TestObject {
public static void main(String[] args) {
// 1.读取hibernate.cfg.xml配置文件
Configuration configuration = new Configuration().configure();
// 2.创建一个会话工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.打开一个会话
Session session = sessionFactory.openSession();
//定义HQL语句
String hql = "select empNo,empName from Employee";
//创建Query对象
Query query = session.createQuery(hql);
// 执行查询
List<Object[]> list = query.list();
for (Object[] employee : list) {
System.out.println(employee[0] + "======" + employee[1]);
}
// 关闭会话
session.close();
}
}
通过构造方法封装成对象
用构造方法实现投影查询,实体类中必须有一个与之对应的带参构造方法
在Employee实体类中生成如下带参构造方法:
public Employee(Integer empNo, String empName, String job) {
this.empNo = empNo;
this.empName = empName;
this.job = job;
}
通过构造方法封装成对象
查询员工的 empNo,empName,job(工号,姓名,职位)
public class TestSelectConstructor {
public static void main(String[] args) {
// 1.读取hibernate.cfg.xml配置文件
Configuration configuration = new Configuration().configure();
// 2.创建一个会话工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.打开一个会话
Session session = sessionFactory.openSession();
//定义HQL语句
//使用构造方法实现投影查询,实体类中必须有一个与之对应的带参构造方法
String hql = "select new Employee(empNo,empName,job) from Employee";
//创建Query对象
Query query = session.createQuery(hql);
//执行查询
List<Employee> list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
// 关闭会话
session.close();
}
}
原生SQL查询
以使用标准的SQL语句完成查询操作,同时可以使用数据库自带的函数,但条件参
数传递的方式要与HQL一致
注意
- 执行SQL语句的是SQLQuery接口中的createSQLQuery()方法
- 需要调用addEntity()方法将表与实体类关联
查询员工信息
public class TestSql {
public static void main(String[] args) {
// 1.读取hibernate.cfg.xml配置文件
Configuration configuration = new Configuration().configure();
// 2.创建一个会话工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.打开一个会话 (获取Session)
Session session = sessionFactory.openSession();
//定义SQL语句
String sql = "select * from employee";
//创建Query对象
NativeQuery sqlQuery = session.createSQLQuery(sql).addEntity(Employee.class);
//执行查询
List<Employee> list = sqlQuery.list();
for (Employee employee : list) {
System.out.println(employee);
}
// 关闭
session.close();
}
}
按条件查询
public class TestSql2 {
public static void main(String[] args) {
// 1.读取hibernate.cfg.xml配置文件
Configuration configuration = new Configuration().configure();
// 2.创建一个会话工厂
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.打开一个会话
Session session = sessionFactory.openSession();
//定义SQL语句
//String sql = "select * from employee where empName like ?1";
String sql = "select * from employee where empName like :empName";
//创建Query对象
NativeQuery sqlQuery = session.createSQLQuery(sql).addEntity(Employee.class);
sqlQuery.setParameter("empName", "%a%");
//执行查询
List<Employee> list = sqlQuery.list();
for (Employee employee : list) {
System.out.println(employee);
}
// 关闭
session.close();
}
}
==================================================
mapper下Department.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
class标签:用于关联实体类,通过name属性指定实体类
name属性:关联实体类的路径
table属性:实体类关联的表名称
-->
<class name="com.hbrj.dao.Department" table="department">
<!-- id标签配置主键字段-->
<!-- name属性:填写该实体类的属性名称(严格区分大小写) -->
<!-- column属性:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省
略 -->
<!-- type属性:填写该属性的数据类型 -->
<id name="deptNo" column="deptNo" type="java.lang.Integer">
<!-- 配置主键生成策略 -->
<!-- assigned:主键由程序提供(非自增)-->
<!-- <generator class="assigned"/>-->
<generator class="increment"></generator>
</id>
<!-- property标签配置普通列名 -->
<property name="deptName" type="java.lang.String" column="deptName"/>
<property name="location" type="java.lang.String" column="location"/>
</class>
</hibernate-mapping>
mapper下Employee.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
class标签:用于关联实体类,通过name属性指定实体类
name属性:关联实体类的路径
table属性:实体类关联的表名称
-->
<class name="com.hbrj.dao.Employee" table="employee" >
<!-- id标签配置主键字段-->
<!-- name属性:填写该实体类的属性名称(严格区分大小写) -->
<!-- column属性:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省
略 -->
<!-- type属性:填写该属性的数据类型 -->
<id name="empNo" column="empNo" type="java.lang.Integer">
<!-- 配置主键生成策略 -->
<!-- assigned:主键由程序提供(非自增)-->
<!-- <generator class="assigned"/>-->
<generator class="increment"></generator>
</id>
<!-- property标签配置普通列名 -->
<property name="empName" type="java.lang.String" column="empName"/>
<property name="job" type="java.lang.String" column="job" />
<property name="salary" type="java.lang.Double" column="salary"/>
<property name="deptNo" type="java.lang.Integer" column="deptNo" />
<property name="hireDate" type="java.util.Date" column="hireDate"/>
</class>
</hibernate-mapping>