Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
将JPA Specification与分页结合的最佳实践_创想鸟

将JPA Specification与分页结合的最佳实践

将JPA Specification与分页结合的最佳实践

本文详细阐述了如何在jpa中利用criteria api实现复杂过滤(如基于不同实体类型的精确搜索)与后端分页的结合。通过`detachedcriteria`构建动态查询,实现多条件筛选,并结合分页参数,提供了一种灵活且高效的数据检索解决方案,尤其适用于需要对多种数据类型进行统一查询并分页的场景。

在现代企业级应用开发中,数据检索是核心功能之一。开发者经常面临的挑战是如何在复杂的过滤条件(例如,需要对不同类型的实体进行精确搜索,并将其结果合并)与高效的后端分页之间找到平衡。传统的JPA Specification在处理单一复杂查询时表现良好,但当需要将多个逻辑上独立的过滤条件“合并”并同时支持分页时,可能会显得不够直观。本文将介绍如何利用JPA的Criteria API,特别是DetachedCriteria,来优雅地解决这一问题。

理解问题场景

假设我们有一个EmployeeEntity,其中包含id、type和name等字段。EmployeeType可以是Teachers或Carers。我们的目标是执行一个过滤搜索,该搜索需要对这两种类型的员工都进行精确匹配,并最终返回一个统一的、支持分页的结果集。这意味着我们需要在一个查询中同时处理多重过滤逻辑,并在此基础上应用分页。

class EmployeeEntity {  private Long id;  private EmployeeType type; // 假设 EmployeeType 是一个独立的实体  private String name;  // Getters and Setters}// 假设 EmployeeType 实体定义如下class EmployeeType {  private Long id;  private String name; // 例如 "Teachers", "Carers"  // Getters and Setters}

使用Criteria API实现复杂过滤与分页

JPA的Criteria API提供了一种类型安全、编程化的方式来构建查询,它非常适合动态查询和复杂条件。DetachedCriteria是Criteria API的一个重要组成部分,它允许我们在Session之外构建查询条件,然后在需要时将其附加到Session上执行。

1. 初始化DetachedCriteria

首先,我们需要为目标实体EmployeeEntity创建一个DetachedCriteria实例。这标志着我们将针对EmployeeEntity执行查询。

import org.hibernate.criterion.DetachedCriteria;import org.hibernate.criterion.Restrictions;// ...// 为 EmployeeEntity 创建 DetachedCriteria 实例DetachedCriteria detachedCriteria = DetachedCriteria.forClass(EmployeeEntity.class, "employee");

这里的”employee”是给EmployeeEntity起的别名,在后续添加条件时可以使用。

2. 添加过滤条件(Specifications)

接下来,我们将添加具体的过滤条件。根据我们的需求,我们需要根据EmployeeType的名称进行过滤。由于EmployeeType是一个关联实体,我们需要使用createAlias来创建别名并进行关联查询。

TeemIp - IPAM and DDI solution TeemIp – IPAM and DDI solution

TeemIp是一个免费、开源、基于WEB的IP地址管理(IPAM)工具,提供全面的IP管理功能。它允许您管理IPv4、IPv6和DNS空间:跟踪用户请求,发现和分配IP,管理您的IP计划、子网空间、区域和DNS记录,符合最佳的DDI实践。同时,TeemIp的配置管理数据库(CMDB)允许您管理您的IT库存并将您的配置项(CIs)与它们使用的IP关联起来。项目源代码位于https://github.com/TeemIP

TeemIp - IPAM and DDI solution 10 查看详情 TeemIp - IPAM and DDI solution

// 关联 EmployeeEntity 的 type 属性到 EmployeeType 实体,并起别名 "employeeType"detachedCriteria.createAlias("employee.type", "employeeType");// 添加过滤条件:员工类型名称等于 "Teachers" 或 "Carers"// 这里的例子展示了如何筛选单一类型,若需同时筛选多个类型,可以使用 Disjunction (OR)// 例如,如果只需要筛选 Teachers:detachedCriteria.add(Restrictions.eq("employeeType.name", "Teachers"));// 如果需要筛选 Teachers 和 Carers 的“并集”结果,可以这样构建:// detachedCriteria.add(Restrictions.or(//     Restrictions.eq("employeeType.name", "Teachers"),//     Restrictions.eq("employeeType.name", "Carers")// ));// 还可以添加其他条件,例如按员工姓名过滤// detachedCriteria.add(Restrictions.ilike("employee.name", "%John%", MatchMode.ANYWHERE));

Restrictions.eq()用于精确匹配,Restrictions.or()用于构建逻辑或条件,可以灵活地组合各种Restrictions来满足复杂的业务逻辑。

3. 实现后端分页

在添加完所有过滤条件后,我们需要处理分页逻辑。分页通常涉及两个参数:当前页码和每页大小。我们需要将页码转换为查询的起始索引(offset)。

/** * 根据页码和每页大小计算查询的起始索引。 * * @param pageNumber 基于1的页码 * @param pageSize 每页显示的记录数 * @return 查询的起始索引 */public Integer calculateOffset(Integer pageNumber, Integer pageSize) {    if (pageNumber == null || pageNumber < 1) {        pageNumber = 1; // 默认第一页    }    if (pageSize == null || pageSize < 1) {        pageSize = 10; // 默认每页10条    }    return (pageNumber - 1) * pageSize;}// 示例用法Integer currentPage = 1; // 假设从前端获取的页码Integer pageSize = 10;   // 假设从前端获取的每页大小Integer offset = calculateOffset(currentPage, pageSize);

4. 执行查询

最后一步是将构建好的DetachedCriteria实例、计算出的offset和pageSize传递给一个执行查询的方法。这个方法通常会使用Hibernate Session来执行Criteria查询并返回结果列表。

import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.criterion.Criteria;import java.util.List;// 假设你有一个 SessionFactory// @Autowired// private SessionFactory sessionFactory;/** * 根据 DetachedCriteria 和分页参数执行查询。 * * @param detachedCriteria 包含所有过滤条件的 DetachedCriteria 实例 * @param offset 查询的起始索引 * @param pageSize 每页显示的记录数 * @return 符合条件并分页后的结果列表 */public List findByCriteria(DetachedCriteria detachedCriteria, Integer offset, Integer pageSize) {    Session session = null;    try {        // 获取当前会话或打开新会话        // session = sessionFactory.getCurrentSession(); // 或 sessionFactory.openSession();        // 这里的 session 获取方式取决于你的Spring/Hibernate配置        // 临时模拟一个 Session 和 Criteria        // 在实际应用中,你需要从 SessionFactory 获取一个真实的 Session        // 并通过 detachedCriteria.getExecutableCriteria(session) 获取 Criteria 实例        Criteria executableCriteria = null; // 实际应为 detachedCriteria.getExecutableCriteria(session);        // 模拟 Criteria 的分页设置        // executableCriteria.setFirstResult(offset);        // executableCriteria.setMaxResults(pageSize);        // 模拟执行查询        // List resultList = executableCriteria.list();        // return resultList;        // 由于没有真实的SessionFactory,这里返回一个空列表作为示例        System.out.println("Executing query with offset: " + offset + ", pageSize: " + pageSize);        System.out.println("Criteria built: " + detachedCriteria.toString());        return List.of(            new EmployeeEntity(1L, new EmployeeType(101L, "Teachers"), "Alice"),            new EmployeeEntity(2L, new EmployeeType(102L, "Carers"), "Bob")        ); // 实际应返回查询结果    } catch (Exception e) {        // 异常处理        e.printStackTrace();        throw new RuntimeException("Error executing criteria query", e);    } finally {        // 关闭会话(如果是由 openSession() 打开的)        // if (session != null && session.isOpen()) {        //     session.close();        // }    }}// 调用示例// List resultList = findByCriteria(detachedCriteria, offset, pageSize);// System.out.println("Query Results: " + resultList);

在实际项目中,findByCriteria方法通常会封装在一个DAO层或Repository中,它会获取当前的Hibernate Session,然后通过detachedCriteria.getExecutableCriteria(session)方法将DetachedCriteria转换为可执行的Criteria对象,并设置分页参数setFirstResult()和setMaxResults(),最后执行list()方法获取结果。

注意事项与最佳实践

Session管理:确保正确管理Hibernate Session。如果使用Spring,通常会通过@Transactional注解或HibernateTemplate来自动管理Session。类型安全:Criteria API是类型安全的,这有助于在编译时捕获错误,而不是在运行时。性能优化:对于非常复杂的查询,尤其是涉及多个JOIN和OR条件时,应考虑查询的性能。使用setResultTransformer可以优化结果集的映射,避免N+1问题。可读性:虽然Criteria API功能强大,但过于复杂的Criteria表达式可能会降低代码的可读性。适当地封装查询构建逻辑,或者考虑将部分复杂查询用JPQL/HQL或原生SQL替代。统一响应:本文的示例展示了如何在一个查询中处理多种类型的过滤并分页。如果“unionized response”意味着需要分别查询不同类型的员工,然后将结果在Java代码中合并并手动分页,那么这种方法可能不适用。但如果目标是构建一个能同时筛选不同类型并在数据库层面分页的单一查询,那么Criteria API是理想选择。

总结

通过DetachedCriteria和Criteria API,我们可以灵活地构建复杂的JPA查询,轻松地将多重过滤条件与后端分页机制结合起来。这种方法不仅提供了强大的查询能力,还保持了代码的类型安全和可维护性,是处理动态和复杂数据检索场景的有效解决方案。开发者可以根据业务需求,通过组合不同的Restrictions和Projections,构建出满足各种需求的查询。

以上就是将JPA Specification与分页结合的最佳实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/984905.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
sql 中 replace 用法_sql 中 replace 替换字符的指南
上一篇 2025年12月1日 20:53:23
Windows禁用驱动程序强制签名,解决个别设备驱动无法正常安装
下一篇 2025年12月1日 20:53:27

相关推荐

  • 文本动画的类选择器应用与优化

    文本动画的类选择器应用与优化文本动画的类选择器应用与优化文本动画的类选择器应用与优化文本动画的类选择器应用与优化

    本文详细介绍了如何将基于ID的文本动画转换为基于类的实现,以支持在多个HTML元素上复用同一动画效果。通过JavaScript动态生成带有自定义CSS变量的标签,并结合CSS @keyframes动画,实现了可灵活应用于页面中任意指定元素的波浪式文本动画,并提供了两种优化方案。 1. 问题背景与目标…

    2026年9月27日 • 用户投稿
    000
  • 在WildFly中集成EJB与JAX-WS:解决部署与访问难题

    在WildFly中集成EJB与JAX-WS:解决部署与访问难题在WildFly中集成EJB与JAX-WS:解决部署与访问难题在WildFly中集成EJB与JAX-WS:解决部署与访问难题在WildFly中集成EJB与JAX-WS:解决部署与访问难题

    本文详细介绍了在WildFly应用服务器上,将EJB(Enterprise JavaBeans)与JAX-WS(Java API for XML Web Services)项目整合到EAR(Enterprise Archive)中的实践。教程涵盖了多模块Maven项目结构、依赖管理、以及如何解决部署…

    2026年9月27日 • 用户投稿
    000
  • Grafana 随笔:安装篇

    Grafana 随笔:安装篇Grafana 随笔:安装篇Grafana 随笔:安装篇Grafana 随笔:安装篇

    grafana 是一款功能强大的开源可视化工具,适合与 zabbix、prometheus 等监控软件配合使用,生成美观且便捷的图表。 前言 前提条件 在开始安装之前,请确保已关闭 Selinux 和防火墙。 sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/…

    2026年9月27日 • 用户投稿
    100
  • 在Java中如何优化线程池大小

    线程池大小应根据任务类型和运行环境优化:CPU密集型设为CPU核心数+1,I/O密集型可设为核心数2~4倍;避免无界队列,选用有界队列并配置合理拒绝策略;通过监控活跃线程、队列长度等指标动态调优;优先使用ThreadPoolExecutor显式配置,避免Executors默认风险。 线程池大小的设置…

    2026年9月27日
    000
  • Java循环中条件判断消息重复输出的优化策略

    Java循环中条件判断消息重复输出的优化策略Java循环中条件判断消息重复输出的优化策略Java循环中条件判断消息重复输出的优化策略Java循环中条件判断消息重复输出的优化策略

    本文探讨了Java循环中因条件判断逻辑不当导致重复输出消息的常见问题。通过引入布尔标志位或利用循环的早期退出机制,可以有效管理循环内的状态,确保在遍历集合时,根据匹配结果只输出一次准确的成功或失败信息,从而提高程序的逻辑清晰度和用户体验。 问题分析:循环中的重复判断 在处理集合数据时,我们经常需要遍…

    2026年9月27日 • 用户投稿
    000
  • Java多线程中竞态条件的原理与实践

    Java多线程中竞态条件的原理与实践Java多线程中竞态条件的原理与实践Java多线程中竞态条件的原理与实践Java多线程中竞态条件的原理与实践

    本文深入探讨了Java多线程编程中的竞态条件(Race Condition),通过分析一个未能产生竞态条件的求和示例,引出并详细演示了如何通过共享可变状态和非原子操作来故意制造竞态条件。文章提供了具体的Java代码示例,解释了竞态条件发生的原因、其在输出中的体现,并强调了在并发编程中识别和避免此类问…

    2026年9月27日 • 用户投稿
    000
  • 构建用户-员工关联的图片上传系统:实现员工为特定用户上传文件

    本文详细阐述了如何构建一个系统,使员工能够为特定用户上传文件(例如QR码),并确保文件与用户准确关联。核心在于优化数据库结构,为上传的文件表引入用户ID外键,并在前端上传表单和后端处理逻辑中实现用户ID的传递与存储,从而实现用户专属内容的管理与展示。 1. 引言:明确用户与文件关联的需求 在许多业务…

    2026年9月27日
    100
  • Android教程:在通用工具类中处理Toast与Context的传递

    Android教程:在通用工具类中处理Toast与Context的传递Android教程:在通用工具类中处理Toast与Context的传递Android教程:在通用工具类中处理Toast与Context的传递Android教程:在通用工具类中处理Toast与Context的传递

    本文旨在解决Android开发中,在非Activity类(如项目管理类)中调用Toast消息时遇到的Context传递问题。通过详细阐述Context在UI操作中的重要性,并提供使用静态方法接收Context参数的解决方案,确保开发者能高效、安全地在任何Activity中复用Toast功能,避免重复…

    2026年9月27日 • 用户投稿
    000
  • laravel怎么动态地修改当前请求的数据库连接_laravel动态修改请求数据库连接方法

    laravel怎么动态地修改当前请求的数据库连接_laravel动态修改请求数据库连接方法laravel怎么动态地修改当前请求的数据库连接_laravel动态修改请求数据库连接方法laravel怎么动态地修改当前请求的数据库连接_laravel动态修改请求数据库连接方法laravel怎么动态地修改当前请求的数据库连接_laravel动态修改请求数据库连接方法

    可通过DB门面切换连接,使用DB::connection(‘mysql_secondary’)执行特定查询;2. 修改模型实例连接,调用setConnection()改变数据源;3. 利用中间件如TenantDatabaseMiddleware解析请求信息并动态设置默认连接;…

    2026年9月27日 • 用户投稿
    300
  • Kafka批处理监听器中反序列化异常的重试策略与实现

    Kafka批处理监听器中反序列化异常的重试策略与实现Kafka批处理监听器中反序列化异常的重试策略与实现Kafka批处理监听器中反序列化异常的重试策略与实现Kafka批处理监听器中反序列化异常的重试策略与实现

    本文详细介绍了如何在Spring Kafka批处理监听器中有效处理并重试反序列化异常。通过修改DefaultErrorHandler以取消对DeserializationException的致命标记,并结合监听器内部对带有null载荷的消息进行异常信息提取和重新抛出,实现对整个批次消息的重试,从而提…

    2026年9月27日 • 用户投稿
    000
  • 如何在Windows和Linux服务器中检测混淆命令

    如何在Windows和Linux服务器中检测混淆命令如何在Windows和Linux服务器中检测混淆命令如何在Windows和Linux服务器中检测混淆命令如何在Windows和Linux服务器中检测混淆命令

    工具介绍 在目前的无文件恶意软件或网络犯罪领域中,命令行混淆已经是很常见的了。为了绕过基于签名的安全检测机制,红队渗透测试以及apt攻击活动都会使用各种专用的混淆/模糊技术。同时,许多代码混淆工具(即执行语法转换工具)都已开源,这也使得网络攻击者们对给定命令进行混淆处理变得越来越容易了。 然而,针对…

    2026年9月27日 • 用户投稿
    900
  • laravel怎么创建和使用Blade组件_laravel Blade组件创建与使用教程

    laravel怎么创建和使用Blade组件_laravel Blade组件创建与使用教程laravel怎么创建和使用Blade组件_laravel Blade组件创建与使用教程laravel怎么创建和使用Blade组件_laravel Blade组件创建与使用教程laravel怎么创建和使用Blade组件_laravel Blade组件创建与使用教程

    Blade组件可提升Laravel应用的UI复用性与维护性,通过php artisan make:component Alert命令创建组件类与视图文件,组件类继承IlluminateViewComponent并在render()方法返回视图。 如果您在开发 Laravel 应用时希望复用某些 UI…

    2026年9月27日 • 用户投稿
    600
  • Java泛型中对象比较的陷阱:为何条件语句失效及equals()方法的正确使用

    Java泛型中对象比较的陷阱:为何条件语句失效及equals()方法的正确使用Java泛型中对象比较的陷阱:为何条件语句失效及equals()方法的正确使用Java泛型中对象比较的陷阱:为何条件语句失效及equals()方法的正确使用Java泛型中对象比较的陷阱:为何条件语句失效及equals()方法的正确使用

    本文深入探讨了Java泛型编程中,当使用==运算符比较对象而非基本类型时,条件语句为何会失效。通过分析==和.equals()方法的本质区别,文章提供了一套清晰的解决方案,并强调了在泛型代码中正确进行对象值比较的关键实践,确保程序逻辑的准确性。 1. Java中对象比较的常见误区 在Java编程中,…

    2026年9月27日 • 用户投稿
    100
  • 月之暗面开源 K2 Vendor Verifier,用于评估 API 供应商的调用能力

    月之暗面开源 K2 Vendor Verifier,用于评估 API 供应商的调用能力月之暗面开源 K2 Vendor Verifier,用于评估 API 供应商的调用能力月之暗面开源 K2 Vendor Verifier,用于评估 API 供应商的调用能力月之暗面开源 K2 Vendor Verifier,用于评估 API 供应商的调用能力

    月之暗面(moonshot ai)近日推出了一款名为 k2 vendor verifier(k2vv) 的开源工具。该项目专注于帮助开发者更直观地评估各类推理服务提供商在工具调用(tool call)任务中的准确率表现。 团队注意到,尽管多个 API 服务商均宣称基于 Kimi K2 开源模型提供服…

    2026年9月27日 • 用户投稿
    200
  • Java中double和long类型详解:精度与范围的选择

    Java中double和long类型详解:精度与范围的选择Java中double和long类型详解:精度与范围的选择Java中double和long类型详解:精度与范围的选择Java中double和long类型详解:精度与范围的选择

    本文旨在深入解析Java中double和long这两种基本数据类型。我们将探讨它们与int和float类型的关键区别,包括存储大小、数值范围和精度。通过本文,你将了解何时以及为何选择double和long,从而编写更高效、更准确的Java程序。我们将通过示例代码和注意事项,助你掌握这些数据类型的应用…

    2026年9月27日 • 用户投稿
    100
  • sublime怎么格式化html_sublime HTML代码美化方法

    sublime怎么格式化html_sublime HTML代码美化方法sublime怎么格式化html_sublime HTML代码美化方法sublime怎么格式化html_sublime HTML代码美化方法sublime怎么格式化html_sublime HTML代码美化方法

    使用HTML-CSS-JS Prettify插件可实现Sublime Text的HTML格式化:1. 安装Package Control;2. 通过命令面板安装插件;3. 按Ctrl+Shift+H(或Cmd+Shift+H)格式化代码;4. 可选配置缩进、保存时自动格式化等;5. 替代插件有JsF…

    2026年9月27日 • 用户投稿
    100
  • Linux 信号

    linux 系统的进程间通信(inter-process communication, ipc)机制包括6种主要类型: 管道(PIPE)、信号(Signal)、命名管道(FIFO)、消息队列(Message Queue)、套接字(Socket)和共享内存(Shared Memory)。信号(Sign…

    2026年9月27日
    100
  • Java中long与double类型详解:与int和float的区别与应用

    Java中long与double类型详解:与int和float的区别与应用Java中long与double类型详解:与int和float的区别与应用Java中long与double类型详解:与int和float的区别与应用Java中long与double类型详解:与int和float的区别与应用

    本文深入探讨Java中的long和double两种基本数据类型,阐述它们与int和float在存储空间、数值范围和精度上的核心差异。通过对比分析,帮助开发者理解何时以及为何选择使用long处理大整数,或使用double应对高精度浮点数计算,从而优化代码性能与数据准确性。 在java编程中,选择合适的…

    2026年9月27日 • 用户投稿
    500
  • laravel怎么实现一个简单的购物车功能_laravel购物车功能实现方法

    laravel怎么实现一个简单的购物车功能_laravel购物车功能实现方法laravel怎么实现一个简单的购物车功能_laravel购物车功能实现方法laravel怎么实现一个简单的购物车功能_laravel购物车功能实现方法laravel怎么实现一个简单的购物车功能_laravel购物车功能实现方法

    答案:可通过Session、数据库或第三方包实现Laravel购物车。首先利用Session临时存储未登录用户数据,通过控制器获取商品信息并操作会话实现添加;其次采用数据库持久化,创建Cart模型关联用户与商品,使用updateOrCreate确保唯一性;最后可借助laravel-shoppingc…

    2026年9月27日 • 用户投稿
    100
  • Java数值类型详解:int、long、float、double的选择与使用

    Java数值类型详解:int、long、float、double的选择与使用Java数值类型详解:int、long、float、double的选择与使用Java数值类型详解:int、long、float、double的选择与使用Java数值类型详解:int、long、float、double的选择与使用

    本文深入探讨Java中int、long、float和double四种基本数值类型的核心差异。我们将从存储空间、数值范围和精度等方面详细比较它们,并提供何时选择特定类型的指导,帮助开发者根据实际需求高效利用这些数据类型,确保数据处理的准确性和效率。 在java编程中,正确选择基本数据类型对于程序的性能…

    2026年9月27日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信