0

0

使用Criteria API实现JPA动态查询与分页

碧海醫心

碧海醫心

发布时间:2025-11-08 15:52:01

|

807人浏览过

|

来源于php中文网

原创

使用criteria api实现jpa动态查询与分页

本文将深入探讨如何利用Hibernate的`DetachedCriteria` API,结合JPA规范实现复杂的多条件动态查询,并有效集成后端分页功能。我们将通过具体示例,演示如何构建灵活的查询条件,包括对关联实体的过滤,以及如何精确控制结果集的页码和大小,从而在统一的响应中高效地处理大量数据。

在现代企业级应用中,数据查询往往需要高度的灵活性和可配置性。用户可能需要根据多种条件进行过滤,例如按类型、名称或其他属性进行精确或模糊匹配。同时,为了优化性能和用户体验,后端分页是不可或缺的功能。当需要结合这些动态过滤条件与分页时,直接使用JPQL或HQL可能会变得复杂且难以维护。此时,Hibernate的Criteria API(特别是DetachedCriteria)提供了一种类型安全、面向对象的方式来构建这些复杂的查询。

1. 理解DetachedCriteria

DetachedCriteria是Hibernate Criteria API的一部分,它允许我们在Session之外构建查询条件。这意味着我们可以在业务逻辑层构建好查询对象,然后将其传递给DAO层或持久化层,在那里附加到Session并执行。这种分离使得查询的构建更加灵活,并且可以轻松地复用。

假设我们有一个EmployeeEntity类,它包含员工的ID、类型和姓名:

// EmployeeEntity.java
import javax.persistence.*;

@Entity
@Table(name = "employees")
public class EmployeeEntity {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @ManyToOne
  @JoinColumn(name = "employee_type_id")
  private EmployeeType type; // 关联到EmployeeType实体

  private String name;

  // 构造函数
  public EmployeeEntity() {}
  public EmployeeEntity(EmployeeType type, String name) {
      this.type = type;
      this.name = name;
  }

  // Getters and setters
  public Long getId() { return id; }
  public void setId(Long id) { this.id = id; }
  public EmployeeType getType() { return type; }
  public void setType(EmployeeType type) { this.type = type; }
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  @Override
  public String toString() {
      return "EmployeeEntity{" +
             "id=" + id +
             ", type=" + (type != null ? type.getName() : "null") +
             ", name='" + name + '\'' +
             '}';
  }
}

// EmployeeType.java
import javax.persistence.*;

@Entity
@Table(name = "employee_types")
public class EmployeeType {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name; // 例如:"Teachers", "Carers"

    // 构造函数
    public EmployeeType() {}
    public EmployeeType(String name) {
        this.name = name;
    }

    // Getters and setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    @Override
    public String toString() {
        return "EmployeeType{" +
               "id=" + id +
               ", name='" + name + '\'' +
               '}';
    }
}

2. 构建动态查询条件

使用DetachedCriteria构建查询的第一步是初始化它,并指定要查询的实体类。

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.MatchMode; // 用于模糊匹配

// 初始化DetachedCriteria,指定要查询的实体类和别名
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(EmployeeEntity.class, "employee");

这里的"employee"是为EmployeeEntity实例指定的别名,方便后续引用其属性。

2.1 添加基本属性过滤

我们可以使用Restrictions类来添加各种过滤条件。例如,如果我们要根据员工姓名进行精确过滤:

LuckyCola工具库
LuckyCola工具库

LuckyCola工具库是您工作学习的智能助手,提供一系列AI驱动的工具,旨在为您的生活带来便利与高效。

下载
// 添加姓名精确匹配条件
detachedCriteria.add(Restrictions.eq("employee.name", "张三"));

// 也可以添加模糊匹配,例如查找名字以"李"开头的员工
// detachedCriteria.add(Restrictions.like("employee.name", "李%", MatchMode.START));

2.2 添加关联实体属性过滤

更常见的场景是需要根据关联实体的属性进行过滤。例如,我们要查找所有类型为“Teachers”的员工。首先,我们需要创建一个别名来引用关联实体EmployeeType:

// 创建关联实体EmployeeType的别名
// "employee.type" 指的是 EmployeeEntity 中的 type 属性
// "employeeType" 是为关联实体 EmployeeType 创建的别名
detachedCriteria.createAlias("employee.type", "employeeType");
// 添加对关联实体属性的过滤条件
detachedCriteria.add(Restrictions.eq("employeeType.name", "Teachers"));

通过createAlias("employee.type", "employeeType"),我们将EmployeeEntity的type属性关联到别名employeeType,然后就可以通过employeeType.name来访问EmployeeType实体的name属性。

2.3 组合多个过滤条件

DetachedCriteria允许我们组合任意数量的条件。例如,查找名为“Alice”且类型为“Carers”的员工:

detachedCriteria.add(Restrictions.eq("employee.name", "Alice"));
detachedCriteria.createAlias("employee.type", "employeeType"); // 再次创建别名,如果之前没有
detachedCriteria.add(Restrictions.eq("employeeType.name", "Carers"));

所有通过add()方法添加的条件默认是AND关系。如果需要OR关系,可以使用Restrictions.or()或Restrictions.disjunction()。

// 查找类型为“Teachers”或“Carers”的员工
detachedCriteria.createAlias("employee.type", "employeeType");
detachedCriteria.add(Restrictions.or(
    Restrictions.eq("employeeType.name", "Teachers"),
    Restrictions.eq("employeeType.name", "Carers")
));

3. 实现后端分页

在构建好查询条件后,下一步就是应用分页逻辑。分页通常需要两个参数:当前页码(pageNumber)和每页大小(pageSize)。

// 假设传入的pageNumber是从1开始的页码,pageSize是每页记录数
int pageNumber = 1; // 示例:请求第一页数据
int pageSize = 10;  // 示例:每页10条记录

// 计算查询结果的起始索引(偏移量)
// 注意:Criteria API的setFirstResult是从0开始的索引
Integer firstResult = (pageNumber - 1) * pageSize;

// 将分页参数应用到DetachedCriteria对象
// 注意:DetachedCriteria本身不直接执行,需要通过Session转换为可执行的Criteria
// 这里只是展示如何计算和应用参数,实际执行在下一步
// criteria.setFirstResult(firstResult); // DetachedCriteria 没有 setFirstResult 方法
// criteria.setMaxResults(pageSize);     // DetachedCriteria 没有 setMax

相关专题

更多
hibernate和mybatis有哪些区别
hibernate和mybatis有哪些区别

hibernate和mybatis的区别:1、实现方式;2、性能;3、对象管理的对比;4、缓存机制。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

136

2024.02.23

Hibernate框架介绍
Hibernate框架介绍

本专题整合了hibernate框架相关内容,阅读专题下面的文章了解更多详细内容。

76

2025.08.06

Java Hibernate框架
Java Hibernate框架

本专题聚焦 Java 主流 ORM 框架 Hibernate 的学习与应用,系统讲解对象关系映射、实体类与表映射、HQL 查询、事务管理、缓存机制与性能优化。通过电商平台、企业管理系统和博客项目等实战案例,帮助学员掌握 Hibernate 在持久层开发中的核心技能。

30

2025.09.02

Hibernate框架搭建
Hibernate框架搭建

本专题整合了Hibernate框架用法,阅读专题下面的文章了解更多详细内容。

64

2025.10.14

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

54

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

46

2025.11.27

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

302

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

703

2023.10.18

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2万人学习

C# 教程
C# 教程

共94课时 | 5.4万人学习

Java 教程
Java 教程

共578课时 | 38.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号