JPA 多条件、多表查询
JPA对于简单的查询操作确实很给力,但是涉及到多表、多条件、分页的场景就不是很好实现了。
可行的解决方案
1、多条件
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>, JpaSpecificationExecutor<T>
使用Specification来实现条件的拼接
2、多表
数据量不大的情况,可以考虑视图,视图实体配置和表的没有任何区别。
3、分页
可以自行实现分页逻辑,也可以使用框架的 Pageable 类。
核心代码示例
// 核心方法 拼接条件public default Predicate getPredocate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb,DataQueryObject dqo) {List<Predicate> predicates = new ArrayList<>();
// 获取查询对象的所有属性Field[] fields = dqo.getClass().getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String queryFiled = null;QueryType queryType = null;Object value = null;Predicate predicate = null;
// 获取属性的 自定义注解类型QueryField annotaion = field.getAnnotation(QueryField.class);
// 如果没有注解 则跳过if(annotaion == null) {continue;}
// 如果注解中 name为空 则用字段名称作为属性名if(!StringUtils.isEmpty(annotaion.name())) {queryFiled = annotaion.name();} else {queryFiled = field.getName();}queryType = annotaion.type();try {value = field.get(dqo);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}
// 判断字段类型是否为空if(value == null && queryType.isNotCanBeNull()) {logger.debug("查询类型:" + queryType + "不允许为空。");continue;}
// 判断注解中 的条件类型switch (queryType) {case EQUAL:Path<Object> equal = getRootByQueryFiled(queryFiled, root);predicate = cb.equal(equal, value);predicates.add(predicate);break;case BEWTEEN:Path<Comparable> between = getRootByQueryFiledComparable(queryFiled, root);QueryBetween queryBetween = null;if(value instanceof QueryBetween) queryBetween = (QueryBetween) value;else continue;predicate = cb.between(between, queryBetween.after, queryBetween.before);predicates.add(predicate);break;case LESS_THAN:Path<Comparable> lessThan = getRootByQueryFiledComparable(queryFiled, root);if(value instanceof QueryBetween) queryBetween = (QueryBetween) value;else continue;predicate = cb.lessThan(lessThan, queryBetween.after);predicates.add(predicate);break;case LESS_THAN_EQUAL:Path<Comparable> lessThanOrEqualTo = getRootByQueryFiledComparable(queryFiled, root);if(value instanceof QueryBetween) queryBetween = (QueryBetween) value;else continue;predicate = cb.lessThanOrEqualTo(lessThanOrEqualTo, queryBetween.after);predicates.add(predicate);break;case GREATEROR_THAN:Path<Comparable> greaterThan = getRootByQueryFiledComparable(queryFiled, root);if(value instanceof QueryBetween) queryBetween = (QueryBetween) value;else continue;predicate = cb.greaterThan(greaterThan, queryBetween.after);predicates.add(predicate);break;case GREATEROR_THAN_EQUAL:Path<Comparable> greaterThanOrEqualTo = getRootByQueryFiledComparable(queryFiled, root);if(value instanceof QueryBetween) queryBetween = (QueryBetween) value;else continue;predicate = cb.lessThanOrEqualTo(greaterThanOrEqualTo, queryBetween.after);predicates.add(predicate);break;case NOT_EQUAL:Path<Object> notEqual = getRootByQueryFiled(queryFiled, root);predicate = cb.notEqual(notEqual, value);predicates.add(predicate);break;case IS_NULL:Path<Object> isNull = getRootByQueryFiled(queryFiled, root);predicate = cb.isNull(isNull);predicates.add(predicate);break;case IS_NOT_NULL:Path<Object> isNotNull = getRootByQueryFiled(queryFiled, root);predicate = cb.isNotNull(isNotNull);predicates.add(predicate);break;case LEFT_LIKE:Path<String> leftLike = getRootByQueryFiledString(queryFiled, root);predicate = cb.like(leftLike, "%" + value.toString());predicates.add(predicate);break;case RIGHT_LIKE:Path<String> rightLike = getRootByQueryFiledString(queryFiled, root);predicate = cb.like(rightLike, value.toString() + "%");predicates.add(predicate);break;case FULL_LIKE:Path<String> fullLike = getRootByQueryFiledString(queryFiled, root);predicate = cb.like(fullLike, "%" + value.toString() + "%");predicates.add(predicate);break;case DEFAULT_LIKE:Path<String> like = getRootByQueryFiledString(queryFiled, root);predicate = cb.like(like, value.toString());predicates.add(predicate);break;case NOT_LIKE:Path<String> notLike = getRootByQueryFiledString(queryFiled, root);predicate = cb.like(notLike, value.toString());predicates.add(predicate);break;case IN:Path<Object> in = getRootByQueryFiled(queryFiled, root);In ins = cb.in(in);List inList = null;if(value instanceof List) {inList = (List) value;}for (Object object : inList) {ins.value(object);}predicates.add(ins);break;default:break;}}
// 如果 为空 代表 没有任何有效的条件if(predicates.size() == 0) {return cb.and();}Object[] list = predicates.toArray();Predicate[] t = new Predicate[predicates.size()];Predicate[] result = predicates.toArray(t);return cb.and(result);}public default Path<Object> getRootByQueryFiled(String queryFiled, Root<T> root) {if(queryFiled.indexOf(".") < 0) {return root.get(queryFiled);} else {return getRootByQueryFiled(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), root.get(queryFiled.substring(0, queryFiled.indexOf("."))));}}public default Path<Object> getRootByQueryFiled(String queryFiled, Path<Object> path) {if(queryFiled.indexOf(".") < 0) {return path.get(queryFiled);} else {return getRootByQueryFiled(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), path.get(queryFiled.substring(0, queryFiled.indexOf("."))));}}public default Path<String> getRootByQueryFiledString(String queryFiled, Root<T> root) {if(queryFiled.indexOf(".") < 0) {return root.get(queryFiled);} else {return getRootByQueryFiledString(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), root.get(queryFiled.substring(0, queryFiled.indexOf("."))));}}public default Path<String> getRootByQueryFiledString(String queryFiled, Path<Object> path) {if(queryFiled.indexOf(".") < 0) {return path.get(queryFiled);} else {return getRootByQueryFiledString(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), path.get(queryFiled.substring(0, queryFiled.indexOf("."))));}}public default Path<Comparable> getRootByQueryFiledComparable(String queryFiled, Root<T> root) {if(queryFiled.indexOf(".") < 0) {return root.get(queryFiled);} else {return getRootByQueryFiledComparable(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), root.get(queryFiled.substring(0, queryFiled.indexOf("."))));}}public default Path<Comparable> getRootByQueryFiledComparable(String queryFiled, Path<Object> path) {if(queryFiled.indexOf(".") < 0) {return path.get(queryFiled);} else {return getRootByQueryFiledComparable(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), path.get(queryFiled.substring(0, queryFiled.indexOf("."))));}}
自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface QueryField {QueryType type();String name() default "";
}
接收参数
@QueryField(type = QueryType.EQUAL, name = "redddlCode")@ApiModelProperty(value="XXX",name="redddlCode",example="S2344")private String redddlCode;
JPA 多条件、多表查询相关推荐
- Spring Data JPA 多条件判空查询
Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询. 使用@Query注解,这种方式可以直接在Repository里面写sql,但是这种方式的问题 ...
- SpringBoot JPA使用Specification多表查询LEFT JOIN
1.Student package com.frank.jpaSpecification.entity;import lombok.AllArgsConstructor; import lombok. ...
- sql case when then else多个条件_SQL-多表查询
一.表的加法 union:将多个表的数据记录按行合并在一起(即多个表的并集),同时返回的结果会删除重复行,重复的记录只保留一行.如果需要保留重复行,可以使用union all 二.表的联结 1.交叉联 ...
- mysql简单聚合函数根据条件单表查询
/*计算product表中所有的记录条数 SELECT COUNT(*) FROM product; *//*获取最高的价格 SELECT MAX(price) FROM product; *//*获 ...
- jpa多条件查询重写Specification的toPredicate方法(转)
Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor.Criteria 查询:是一种类型安全和更面向对象的查询 . 这个接 ...
- 基于SpringDataJpa的mysql动态分页多表查询
基于SpringDataJpa的mysql动态分页多表查询 由于这篇文章预计篇幅会很长,关于Spring Data JPA的知识就简短的分享,更多的请自行度娘,JPA 封装了很多查询的接口,但今天要讲 ...
- mysql第四篇:数据操作之多表查询
mysql第四篇:数据操作之多表查询 一.多表联合查询 #创建部门 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment P ...
- 039_MySQL_多表查询
#创建部门 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment PRIMARY KEY,dname VARCHAR(50) ...
- mysql从多个表查询数据类型_MySQL 之 多表查询
阅读目录 一.多表联合查询 #创建部门CREATE TABLE IF NOT EXISTSdept ( didint not null auto_increment PRIMARY KEY, dnam ...
- Java数据库篇6——多表查询
Java数据库篇6--多表查询 1.笛卡尔积 交叉连接查询 设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), ...
最新文章
- 人工智能从业者应该从哪里去寻找和阅读顶级论文?
- 对比自监督学习浪潮迅猛来袭,你准备好了吗?
- 大一统的宇宙与太极原理之随想
- JAVA项目实训struts2_Java Web项目搭建过程记录(struts2)
- python学习必备知识点: 装饰器
- IBASE archive write processing report RIBARCHA
- 漫步微积分三十——定积分的性质
- Topic model相关文章总结
- 在PhpStorm中管理GitHub代码仓库的使用方法
- exe文件注册服务的方法
- Hyper-V 3.0服务器虚拟化:打造坚固的云
- 牛逼!9种不同的方法帮助你提高国内访问Github的速度到2MB/s以上...
- python实例编写(7)---测试报告与测试套件(多个py文件,1个py文件内多个用例)
- python的分号用英文还是中文_Python中的分号
- 小可乐手机救砖+恢复通信录
- Matlab程序——3d玫瑰
- python:烤地瓜程序
- 数据库防火墙应具备哪些能力
- mirrors.aliyun.com 无法解析域名
- WordPress 搭建超级好看的主题博客