0

0

JAVA Spring Data JPA中的动态查询代码详解

Y2J

Y2J

发布时间:2017-04-25 16:42:56

|

2843人浏览过

|

来源于php中文网

原创

spring data jpa大大的简化了我们持久层的开发,但是实际应用中,我们还是需要动态查询的。

比如,前端有多个条件,这些条件很多都是可选的,那么后端的SQL,就应该是可以定制的,在使用hibernate的时候,可以通过判断条件来拼接SQL(HQL),当然,Spring Data JPA在简化我们开发的同时,也是提供了支持的。

通过实现Criteria二实现的动态查询,需要我们的Repo接口继承JpaSpecificationExecutor接口,这是个泛型接口。

然后查询的时候,传入动态查询参数,分页参数等即可。

使用起来很简单,不过为了知其所以然,先介绍一下Criteria API。

立即学习Java免费学习笔记(深入)”;

Criteria API

如果编译器能够对查询执行语法正确性检查,那么对于 Java 对象而言该查询就是类型安全的。Java™Persistence API (JPA) 的 2.0 版本引入了 Criteria API,这个 API 首次将类型安全查询引入到 Java 应用程序中,并为在运行时动态地构造查询提供一种机制。本文介绍如何使用 Criteria API 和与之密切相关的 Metamodel API 编写动态的类型安全查询。

在使用Spring Data JPA的时候,只要我们的Repo层继承JpaSpecificationExecutor接口就可以使用Specification进行动态查询了,我们先看下JpaSpecificationExecutor接口:

public interface JpaSpecificationExecutor { 
 T findOne(Specification spec); 
 List findAll(Specification spec); 
 Page findAll(Specification spec, Pageable pageable); 
 List findAll(Specification spec, Sort sort); 
 long count(Specification spec); 
}

可以看到提供了5个方法,方法的参数和返回值已经很明显的表达了其意图。其中的参数,Pageable和Sort应该是比较简单的,分别是分页参数和排序参数,而重点就是Specification参数,先看下这个接口的定义:

public interface Specification { 
 Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb); 
}

其中就一个方法,返回的是动态查询的数据结构。


javax.persistence.criteria.Predicate toPredicate(javax.persistence.criteria.Root root,
javax.persistence.criteria.CriteriaQuery query,
javax.persistence.criteria.CriteriaBuilder cb);

这里使用的都是Java EE中的规范,具体实现本人采用的是Hibernate,当然也可以选择其他实现了JPA规范的数据持久层框架。
这里需要再次回过头看看Criteria API中的一些东西:

Criteria 查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。

英特尔AI工具
英特尔AI工具

英特尔AI与机器学习解决方案

下载

CriteriaQuery接口:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用

Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似

1:Root实例是类型化的,且定义了查询的FROM子句中能够出现的类型。

2:查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。

3:Criteria查询,可以有多个查询根。

4:AbstractQuery是CriteriaQuery 接口的父类,它提供得到查询根的方法。CriteriaBuilder接口:用来构建CritiaQuery的构建器对象Predicate:一个简单或复杂的谓词类型,其实就相当于条件或者是条件组合

其中支持的方法非常之强大,下面给出一个示例,大家可以参考一下,同样的,可以根据示例,自己可以写出更为复杂的查询:

Repo接口:

public interface DevHREmpConstrastDao 
 extends JpaRepository,JpaSpecificationExecutor

查询实例1:

/** 
 * 条件查询时动态组装条件 
 */ 
private Specification where( 
  final String corg,final String name,final String type,final String date,final String checker){ 
 return new Specification() { 
  @Override 
  public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { 
   List
 predicates = new ArrayList
(); 
   //机构 
   if(corg!=null&&!corg.equals("")){ 
    List orgIds = organizationDao.findByName("%"+corg+"%"); 
    if(orgIds.size()>0&&orgIds.size()<1000) 
     predicates.add(root.get("confirmOrgNo").in(orgIds));//confirmOrgNo 
   } 
   //名字 
   if(name!=null&&!name.equals("")){ 
    List userIds = userDao.findByName(name); 
    if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
     predicates.add(root.get("hrUserName").in(userIds)); 
   } 
   //类型 
   if(type!=null&&!type.equals("")) 
    predicates.add(cb.equal(root.get("hrUpdateType"),type)); 
   //日期 
   if(date!=null&&!date.equals("")){ 
    //处理时间 
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
    Date startDate; 
    Date endDate; 
    try { 
     startDate = format.parse(date); 
    } catch (ParseException e) { 
     startDate = new Date(946656000000L);//2000 01 01 
    } 
    endDate = startDate; 
    Calendar calendar = Calendar.getInstance() ; 
    calendar.setTime(endDate); 
    calendar.add(Calendar.DATE, 1); 
    endDate = calendar.getTime(); 
    calendar = null; 
    predicates.add(cb.between(root.get("insDate"),startDate,endDate)); 
   } 
   //审核人 
   if(checker!=null&&!checker.equals("")){ 
    List userIds = userDao.findByName(checker); 
    if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
     predicates.add(root.get("confirmUserId").in(userIds)); 
   } 
   return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); 
  } 
 }; 
}

查询实例2:

/** 
 * 条件查询时动态组装条件 
 */ 
 private Specification where( 
   final String corg,final String name,final String type,final String date,final String checker){ 
  return new Specification() { 
   @Override 
   public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { 
    List
 predicates = new ArrayList
(); 
    //机构 
    if(corg!=null&&!corg.equals("")){ 
     List orgIds = organizationDao.findByName("%"+corg+"%"); 
     if(orgIds.size()>0&&orgIds.size()<1000) 
      predicates.add(root.get("confirmOrgNo").in(orgIds));//confirmOrgNo 
    } 
    //名字 
    if(name!=null&&!name.equals("")){ 
     List userIds = userDao.findByName(name); 
     if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
      predicates.add(root.get("hrUserName").in(userIds)); 
    } 
    //类型 
    if(type!=null&&!type.equals("")) 
     predicates.add(cb.equal(root.get("hrUpdateType"),type)); 
    //日期 
    if(date!=null&&!date.equals("")){ 
     //处理时间 
     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
     Date startDate; 
     Date endDate; 
     try { 
      startDate = format.parse(date); 
     } catch (ParseException e) { 
      startDate = new Date(946656000000L);//2000 01 01 
     } 
     endDate = startDate; 
     Calendar calendar = Calendar.getInstance() ; 
     calendar.setTime(endDate); 
     calendar.add(Calendar.DATE, 1); 
     endDate = calendar.getTime(); 
     calendar = null; 
     predicates.add(cb.between(root.get("insDate"),startDate,endDate)); 
    } 
    //审核人 
    if(checker!=null&&!checker.equals("")){ 
     List userIds = userDao.findByName(checker); 
     if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 
      predicates.add(root.get("confirmUserId").in(userIds)); 
    } 
    return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); 
   } 
  }; 
 }

然后调用dao层方法传入where()方法返回的参数即可。

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

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

6

2026.01.29

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Spring中文手册
Spring中文手册

共0课时 | 0人学习

马士兵spring视频教程
马士兵spring视频教程

共25课时 | 9.1万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.0万人学习

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

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