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

比如,前端有多个条件,这些条件很多都是可选的,那么后端的SQL,就应该是可以定制的,在使用hibernate的时候,可以通过判断条件来拼接SQL(HQL),当然,Spring Data JPA在简化我们开发的同时,也是提供了支持的。
通过实现Criteria二实现的动态查询,需要我们的Repo接口继承JpaSpecificationExecutor接口,这是个泛型接口。
然后查询的时候,传入动态查询参数,分页参数等即可。
使用起来很简单,不过为了知其所以然,先介绍一下Criteria API。
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> {
T findOne(Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);
}
可以看到提供了5个方法,方法的参数和返回值已经很明显的表达了其意图。其中的参数,Pageable和Sort应该是比较简单的,分别是分页参数和排序参数,而重点就是Specification参数,先看下这个接口的定义:
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
其中就一个方法,返回的是动态查询的数据结构。
javax.persistence.criteria.Predicate toPredicate(javax.persistence.criteria.Root<T> root, javax.persistence.criteria.CriteriaQuery<?> query, javax.persistence.criteria.CriteriaBuilder cb);
这里使用的都是Java EE中的规范,具体实现本人采用的是Hibernate,当然也可以选择其他实现了JPA规范的数据持久层框架。
这里需要再次回过头看看Criteria API中的一些东西:
Criteria 查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。
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<DevHREmpConstrast, Long>,JpaSpecificationExecutor<DevHREmpConstrast>
查询实例1:
/**
* 条件查询时动态组装条件
*/
private Specification<DevHREmpConstrast> where(
final String corg,final String name,final String type,final String date,final String checker){
return new Specification<DevHREmpConstrast>() {
@Override
public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<Predicate>();
//机构
if(corg!=null&&!corg.equals("")){
List<String> orgIds = organizationDao.findByName("%"+corg+"%");
if(orgIds.size()>0&&orgIds.size()<1000)
predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo
}
//名字
if(name!=null&&!name.equals("")){
List<String> userIds = userDao.findByName(name);
if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了
predicates.add(root.<String>get("hrUserName").in(userIds));
}
//类型
if(type!=null&&!type.equals(""))
predicates.add(cb.equal(root.<String>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.<Date>get("insDate"),startDate,endDate));
}
//审核人
if(checker!=null&&!checker.equals("")){
List<String> userIds = userDao.findByName(checker);
if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了
predicates.add(root.<String>get("confirmUserId").in(userIds));
}
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
};
}
查询实例2:
/**
* 条件查询时动态组装条件
*/
private Specification<DevHREmpConstrast> where(
final String corg,final String name,final String type,final String date,final String checker){
return new Specification<DevHREmpConstrast>() {
@Override
public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<Predicate>();
//机构
if(corg!=null&&!corg.equals("")){
List<String> orgIds = organizationDao.findByName("%"+corg+"%");
if(orgIds.size()>0&&orgIds.size()<1000)
predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo
}
//名字
if(name!=null&&!name.equals("")){
List<String> userIds = userDao.findByName(name);
if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了
predicates.add(root.<String>get("hrUserName").in(userIds));
}
//类型
if(type!=null&&!type.equals(""))
predicates.add(cb.equal(root.<String>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.<Date>get("insDate"),startDate,endDate));
}
//审核人
if(checker!=null&&!checker.equals("")){
List<String> userIds = userDao.findByName(checker);
if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了
predicates.add(root.<String>get("confirmUserId").in(userIds));
}
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
};
}
然后调用dao层方法传入where()方法返回的参数即可。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# spring
# data
# jpa
# 动态
# 查询
# 动态查询
# Spring Data JPA实现动态查询的两种方法
# springdata jpa使用Example快速实现动态查询功能
# 详解Spring Data JPA动态条件查询的写法
# Spring JPA使用CriteriaBuilder动态构造查询方式
# 太多
# 就不
# 的是
# 都是
# 管了
# 子句
# 多个
# 分页
# 先看
# 应该是
# 首次
# 数据结构
# 可以通过
# 很简单
# 或者是
# 可以看到
# 可选
# 大大的
# 与之
# 可以选择
相关文章:
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
官网自助建站平台指南:在线制作、快速建站与模板选择全解析
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
在线教育网站制作平台,山西立德教育官网?
ui设计制作网站有哪些,手机UI设计网址吗?
C++中引用和指针有什么区别?(代码说明)
公司网站制作价格怎么算,公司办个官网需要多少钱?
制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?
早安海报制作网站推荐大全,企业早安海报怎么每天更换?
C#如何序列化对象为XML XmlSerializer用法
打鱼网站制作软件,波克捕鱼官方号怎么注册?
详解jQuery中基本的动画方法
宝塔建站无法访问?如何排查配置与端口问题?
建站之星客服服务时间及联系方式如何?
建站之星云端配置指南:模板选择与SEO优化一键生成
如何在新浪SAE免费搭建个人博客?
网站建设制作、微信公众号,公明人民医院怎么在网上预约?
建站ABC备案流程中有哪些关键注意事项?
如何用5美元大硬盘VPS安全高效搭建个人网站?
宝盒自助建站智能生成技巧:SEO优化与关键词设置指南
网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?
测试制作网站有哪些,测试性取向的权威测试或者网站?
网站制作企业,网站的banner和导航栏是指什么?
如何快速重置建站主机并恢复默认配置?
如何选择适合PHP云建站的开源框架?
番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?
建站之星CMS建站配置指南:模板选择与SEO优化技巧
,如何利用word制作宣传手册?
如何配置IIS站点权限与局域网访问?
浅谈Javascript中的Label语句
如何通过cPanel快速搭建网站?
如何用低价快速搭建高质量网站?
建站之星后台密码遗忘?如何快速找回?
SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?
定制建站如何定义?其核心优势是什么?
如何零成本快速生成个人自助网站?
内部网站制作流程,如何建立公司内部网站?
如何在香港免费服务器上快速搭建网站?
建站之星后台管理:高效配置与模板优化提升用户体验
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
免费ppt制作网站,有没有值得推荐的免费PPT网站?
,购物网站怎么盈利呢?
浅析上传头像示例及其注意事项
如何生成腾讯云建站专用兑换码?
单页制作网站有哪些,朋友给我发了一个单页网站,我应该怎么修改才能把他变成自己的呢,请求高手指点迷津?
建站之星IIS配置教程:代码生成技巧与站点搭建指南
广州顶尖建站服务:企业官网建设与SEO优化一体化方案
如何破解联通资金短缺导致的基站建设难题?
如何在阿里云虚拟主机上快速搭建个人网站?
浙江网站制作公司有哪些,浙江栢塑信息技术有限公司定制网站做的怎么样?
*请认真填写需求信息,我们会在24小时内与您取得联系。