概述

  ORM映射为我们带来便利的同时,也失去了较大灵活性,如果SQL较复杂,要进行动态查询,那必定是一件头疼的事情(也可能是lz还没发现好的方法),记录下自己用的三种复杂查询方式。

环境

springBoot

IDEA2017.3.4

JDK8

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.xmlxy</groupId><artifactId>seasgame</artifactId><version>0.0.1-SNAPSHOT</version><name>seasgame</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--数据库连接--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 热启动等 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><!--Java bean 实体--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--swagger2 API 测试工具 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!--安全框架认证--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.2.2</version><classifier>jdk15</classifier></dependency><!--汉字转拼音--><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.1</version></dependency><!-- thymeleaf模板 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>移除嵌入式tomcat插件<exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency>--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency></dependencies><packaging>war</packaging><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins><finalName>seasgame</finalName><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><encoding>${project.build.sourceEncoding}</encoding><source>1.7</source><target>1.7</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><testFailureIgnore>true</testFailureIgnore></configuration></plugin></plugins></pluginManagement></build></project>

@Query

当一个SQL较为复杂时,第一个想到的就是原生的SQL语句。如果只是简单的查询,那情况还没这么糟糕

 @Query(value = " SELECT IFNULL(sum(right_num),0) sumRight FROM t_record WHERE record_owner_id = ?1 AND responder_no = ?2 ",nativeQuery = true)Map<String,Object> sumRightNum(int studentId,int responderNo);

但如果需要进行动态查询,或更改,那这个value就变得复杂了。

package com.xmlxy.seasgame.dao;import com.xmlxy.seasgame.entity.ScoreEntity;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;import java.util.List;/*** * Description: * @author hwc* @date 2019/9/5* @return
*/
public interface ScoreDao extends CrudRepository<ScoreEntity,Integer>
{/** * * Description:*@param scoreEntity* @author hwc* @date 2019/9/6*/@Transactional(rollbackFor = Exception.class)@Modifying@Query(value = "UPDATE t_score t SET " +"t.responder_no = CASE WHEN :#{#scoreEntity.responderNo} IS NULL THEN t.responder_no ELSE :#{#scoreEntity.responderNo} END," +"t.max_level = CASE WHEN :#{#scoreEntity.maxLevel} IS NULL THEN t.max_level ELSE :#{#scoreEntity.maxLevel} END," +"t.right_num = CASE WHEN :#{#scoreEntity.rightNum} IS NULL THEN t.right_num ELSE :#{#scoreEntity.rightNum} END," +"t.use_time = CASE WHEN :#{#scoreEntity.userTime} IS NULL THEN t.use_time ELSE :#{#scoreEntity.userTime} END WHERE student_id = :#{#scoreEntity.getStudentId()}",nativeQuery = true)void updateScore(@Param("scoreEntity") ScoreEntity scoreEntity);
}

JPQL

如果Java代码内发出JPQL查询,就需要利用到EntityManager的响应方法了。一般执行以下流程

  1. 获取一个EntityManager实例
  2. 调用实例的方法createQuery,创建一个Query实例,如果有需要可以指定检索的最大数量和起始位置
  3. 使用Query方法getResultList执行查询,当然更新和删除操作得使用executeUpdate执行

进行一个复杂的动态SQL查询

   public Page<RankEntity> getScoreByRank(int gradeId,int classId,Pageable pageable){StringBuilder countSelectSql = new StringBuilder("");countSelectSql.append(" SELECT COUNT(*) ");countSelectSql.append(" FROM ");countSelectSql.append(" t_score s, ");countSelectSql.append(" t_student st   ");countSelectSql.append(" WHERE ");countSelectSql.append(" s.student_id = st.student_id ");StringBuilder selectSql = new StringBuilder();selectSql.append(" SELECT s.student_id,st.real_name,st.student_class,s.max_level,s.use_time,s.right_num ");selectSql.append(" FROM t_score s ");selectSql.append(" JOIN t_student st ON s.student_id = st.student_id ");selectSql.append(" WHERE 1 = 1 ");Map<String,Object> params = new HashMap<>();StringBuilder whereSql = new StringBuilder();if (gradeId != -1){whereSql.append(" AND st.student_grade = :student_grade ");params.put("student_grade",gradeId);}/**班级ID*/if (classId != -1){whereSql.append(" AND st.student_class = :classId ");params.put("classId",classId);}String orderSql = " ORDER BY s.max_level DESC,s.use_time,s.right_num ASC ";String countSql = new StringBuilder().append(countSelectSql).append(whereSql).toString();Query countQuery = entityManager.createNativeQuery(countSql);for (Map.Entry<String,Object> entry : params.entrySet()){countQuery.setParameter(entry.getKey(),entry.getValue());}BigInteger totalCount = (BigInteger)countQuery.getSingleResult();String querySql = new StringBuilder().append(selectSql).append(whereSql).append(orderSql).toString();Query query = entityManager.createNativeQuery(querySql,RankEntity.class);for (Map.Entry<String,Object> entry:params.entrySet()){query.setParameter(entry.getKey(),entry.getValue());}query.setFirstResult((int) pageable.getOffset());query.setMaxResults(pageable.getPageSize());List<RankEntity> rankEntities = query.getResultList();Page<RankEntity> page = new PageImpl<>(rankEntities,pageable,totalCount.longValue());return page;}

注意:如果没有重新定义Pageable那么pageNumber必须减1,因为是从0开始的。

Criteria

这是一种规范查询是以元模型的概念为基础的,这个元模型可以是实体累,嵌入类,或者映射的父类,简单介绍几个里面用到接口。

CriteraQuery是一个特定的顶层查询对象,里面包含select,from,where,order by等各个部分,然而他只对实体类或嵌入类的标准查询起作用。

Root标准查询的根对象,根定义了实体类型,是你想要查询要获得的结果,也可以添加查询条件,结合实体管理对象得到查询的对象。

CriteriaBuilder接口用来构建CritiaQuery的构建器

StudentEntity类

package com.xmlxy.seasgame.entity;import io.swagger.annotations.ApiModel;
import lombok.Data;import javax.persistence.*;
import javax.print.attribute.standard.MediaSize;
import java.io.Serializable;/*** * Description:学生对象* @param* @author hwc* @date 2019/8/8
*/
@Entity
@Table(name = "t_base_student")
@ApiModel
@Data
public class StudentEntity implements Serializable
{private static final long serialVersionUID = 546L;@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "student_id")private Integer studentId;@Column(name = "student_grade")private Integer studentGrade;@Column(name = "student_class")private Integer studentClass;@Column(name = "address")private String address;@Column(name = "telephone")private Integer telephone;@Column(name = "real_name")private String realName;@Column(name = "id_number")private String idNumber;@Column(name = "study_id")private String studyId;@Column(name = "is_delete")private int isDelete;@Column(name = "uuid")private String uuid;}

dao层

public interface StudentDao extends JpaRepository<StudentEntity,Integer>,JpaSpecificationExecutor
{
}

动态查询

    public Page<StudentEntity> getTeacherClassStudent(int pageNumber,int pageSize,int gradeId, int classId,String keyword){pageNumber = pageNumber < 0 ? 0 : pageNumber;pageSize = pageSize < 0 ? 10 : pageSize;Specification<StudentEntity> specification = new Specification<StudentEntity>(){@Overridepublic Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder){//page : 0 开始, limit : 默认为 10List<Predicate> predicates = new ArrayList<>();predicates.add(criteriaBuilder.equal(root.get("studentGrade"),gradeId));predicates.add(criteriaBuilder.equal(root.get("studentClass"),classId));if (!Constant.isEmptyString(keyword)){predicates.add(criteriaBuilder.like(root.get("realName").as(String.class),"%" + keyword + "%"));}return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));}};/*studentId必须是实体类属性与数据库对应,否则报ropertyReferenceException异常*/PageRequest page = new PageRequest(pageNumber,pageSize,Sort.Direction.ASC,"studentId");Page<StudentEntity> pages = studentDao.findAll(specification,page);return pages;}

因为这个项目应用比较简单,所以条件只有一个,如果条件较多,甚至可以定义一个专门的类去接收拼接参数,然后判断,成立就add进去。

转载一篇写得不错的文章:https://blog.csdn.net/u010775025/article/details/80497986

转载于:https://www.cnblogs.com/dslx/p/11474453.html

JPA多条件复杂SQL动态分页查询相关推荐

  1. jpa mysql sql分页查询语句_JPA多条件复杂SQL动态分页查询功能

    概述 ORM映射为我们带来便利的同时,也失去了较大灵活性,如果SQL较复杂,要进行动态查询,那必定是一件头疼的事情(也可能是lz还没发现好的方法),记录下自己用的三种复杂查询方式. 环境 spring ...

  2. Mybatis+MySQL动态分页查询数据经典案例

    最近在用Mybatis做项目的时候遇到了不少问题,今天我就在这和大家分享一下,稀稀拉拉的研究了两天,终于搞好了! 开发人员:1111 开发软件:Myeclipse 用到的框架技术:Mybatis 数据 ...

  3. Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)

    最近在用Mybatis做项目的时候遇到了不少问题,今天我就在这和大家分享一下,稀稀拉拉的研究了两天,终于搞好了! 开发人员:1111 开发软件:Myeclipse 用到的框架技术:Mybatis 数据 ...

  4. Mybatis+mysql动态分页查询数据案例——房屋信息的接口(IHouseDao)

    package cn.bdqn.mhouse.dao;import java.util.List;import cn.bdqn.mhouse.entity.House; import cn.bdqn. ...

  5. pagehelper+sqlserver 不支持该sql转换为分页查询

    起因: 今天遇到一个问题,从navicat写的语句放到mybatis中执行,pagehelper分页报错.pagehelper 不支持该sql转换为分页查询.找了很久问题,网上各种答案都不能解决问题: ...

  6. SQL Server分页查询方法整理

    SQL Server数据库分页查询一直是SQL Server的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID.YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页 ...

  7. Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...

  8. SQL教程——分页查询

    本教程中所使用的数据库的建表语句都在"SQL教程--索引"这篇文章中,点击链接直达:索引&建表语句 摘要:本文主要介绍SQL的子查询分页 分页查询 应用场景:当要显示的数据 ...

  9. java中动态查询条件,Java实现动态添加查询条件

    今天遇到一个问题,就是需要根据前端页面发送的条件查询数据库记录,但是前端发送的条件是不确定的.如果使用mybatis的xml方法可以使用if标签灵活的添加判断条件,但是现在我使用的就是单纯的sql. ...

最新文章

  1. mysql depended_query 优化案例一则
  2. IDC最新报告:阿里语音AI登顶中国No.1
  3. tcp/ip 协议栈Linux内核源码分析八 路由子系统分析三 路由表
  4. HTML中的Content-Type的类型
  5. CompletableFuture详解~thenApplyAsync
  6. Spring Cloud 服务注册与发现 [ eureka ]
  7. android中MVC,MVP和MVVM三种模式详解析
  8. LaTex 加粗(加黑)的方式
  9. Nginx/Apache 对图片,css,js等优化,静态页面设置过期时间
  10. orcadcapture安装_OrCAD Capture CIS初学者快速上手指导教程
  11. 全国大学FTP列表!绝对经典!!!
  12. 数据库是根和数据仓库是魂
  13. 扫描二维码进入小程序超详细过程
  14. 有哪些比较好的企业内部管理软件?公认的5个高效管理软件介绍
  15. python计算模型psi_模型稳定度指标PSI与IV
  16. 求点赞、被点赞,社交网络用户对点赞又爱又恨
  17. 杭电oj第1000题—— A + B Problem
  18. ffmpeg 之 dash
  19. java判断是否安装了pdf_java判断上传文件是否为pdf java图像上传中如何判断是否是jpg格式...
  20. 慢性子的网易,走不快的B端?

热门文章

  1. Spring---基于Spring IOC的小程序
  2. react+redux+generation-modation脚手架搭建一个todolist
  3. (转)SQLServer实例讲解
  4. PDFMate PDF Converter Pro
  5. ECharts-图表回执组件
  6. codeforces 1045 D. Interstellar battle
  7. 配置SMB共享 、 配置NFS共享
  8. IBM收购以色列应用发现公司EZSource
  9. 两个数组a[N],b[N],其中A[N]的各个元素值已知,现给b[i]赋值,b[i] = a[0]*a[1]*a[2]…*a[N-1]/a[i];...
  10. 《众妙之门——网页排版设计制胜秘诀》——3.4 展现品牌视觉的同时保持网页的可读性...