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 多条件、多表查询相关推荐

  1. Spring Data JPA 多条件判空查询

    Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询. 使用@Query注解,这种方式可以直接在Repository里面写sql,但是这种方式的问题 ...

  2. SpringBoot JPA使用Specification多表查询LEFT JOIN

    1.Student package com.frank.jpaSpecification.entity;import lombok.AllArgsConstructor; import lombok. ...

  3. sql case when then else多个条件_SQL-多表查询

    一.表的加法 union:将多个表的数据记录按行合并在一起(即多个表的并集),同时返回的结果会删除重复行,重复的记录只保留一行.如果需要保留重复行,可以使用union all 二.表的联结 1.交叉联 ...

  4. mysql简单聚合函数根据条件单表查询

    /*计算product表中所有的记录条数 SELECT COUNT(*) FROM product; *//*获取最高的价格 SELECT MAX(price) FROM product; *//*获 ...

  5. jpa多条件查询重写Specification的toPredicate方法(转)

    Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor.Criteria 查询:是一种类型安全和更面向对象的查询 . 这个接 ...

  6. 基于SpringDataJpa的mysql动态分页多表查询

    基于SpringDataJpa的mysql动态分页多表查询 由于这篇文章预计篇幅会很长,关于Spring Data JPA的知识就简短的分享,更多的请自行度娘,JPA 封装了很多查询的接口,但今天要讲 ...

  7. mysql第四篇:数据操作之多表查询

    mysql第四篇:数据操作之多表查询 一.多表联合查询 #创建部门 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment P ...

  8. 039_MySQL_多表查询

    #创建部门 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment PRIMARY KEY,dname VARCHAR(50) ...

  9. mysql从多个表查询数据类型_MySQL 之 多表查询

    阅读目录 一.多表联合查询 #创建部门CREATE TABLE IF NOT EXISTSdept ( didint not null auto_increment PRIMARY KEY, dnam ...

  10. Java数据库篇6——多表查询

    Java数据库篇6--多表查询 1.笛卡尔积 交叉连接查询 设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), ...

最新文章

  1. 人工智能从业者应该从哪里去寻找和阅读顶级论文?
  2. 对比自监督学习浪潮迅猛来袭,你准备好了吗?
  3. 大一统的宇宙与太极原理之随想
  4. JAVA项目实训struts2_Java Web项目搭建过程记录(struts2)
  5. python学习必备知识点: 装饰器
  6. IBASE archive write processing report RIBARCHA
  7. 漫步微积分三十——定积分的性质
  8. Topic model相关文章总结
  9. 在PhpStorm中管理GitHub代码仓库的使用方法
  10. exe文件注册服务的方法
  11. Hyper-V 3.0服务器虚拟化:打造坚固的云
  12. 牛逼!9种不同的方法帮助你提高国内访问Github的速度到2MB/s以上...
  13. python实例编写(7)---测试报告与测试套件(多个py文件,1个py文件内多个用例)
  14. python的分号用英文还是中文_Python中的分号
  15. 小可乐手机救砖+恢复通信录
  16. Matlab程序——3d玫瑰
  17. python:烤地瓜程序
  18. 数据库防火墙应具备哪些能力
  19. mirrors.aliyun.com 无法解析域名
  20. WordPress 搭建超级好看的主题博客

热门文章

  1. java解析xml 字符串_Java解析XML字符串
  2. 我们大家都知道mysql_10个mysql中select语句的简单用法
  3. java buqi_Java 异常
  4. uboot向linux传递输出任何log信息的方法
  5. 数据结构 | 链表:1074
  6. hdu 1231 最大连续子序列 ,1003 Max Sum;
  7. reveal end of document
  8. ERP通用存储过程封装(三)
  9. 使用CXF发布WebService服务简单实例
  10. 虚拟机安装 xp步骤(参照百度文库)