千家信息网

怎么实现JPA多条件复杂SQL动态分页查询功能

发表于:2025-11-14 作者:千家信息网编辑
千家信息网最后更新 2025年11月14日,这篇文章给大家分享的是有关怎么实现JPA多条件复杂SQL动态分页查询功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述ORM映射为我们带来便利的同时,也失去了较大灵活性
千家信息网最后更新 2025年11月14日怎么实现JPA多条件复杂SQL动态分页查询功能

这篇文章给大家分享的是有关怎么实现JPA多条件复杂SQL动态分页查询功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

概述

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

环境

springBoot

IDEA2017.3.4

JDK8

pom.xml

4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.6.RELEASE com.xmlxy seasgame 0.0.1-SNAPSHOT seasgame Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java runtime org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-data-jpa io.springfox springfox-swagger2 2.8.0 io.springfox springfox-swagger-ui 2.8.0 org.springframework.boot spring-boot-configuration-processor true org.springframework.boot spring-boot-starter-security net.sf.json-lib json-lib 2.2.2 jdk15 com.belerweb pinyin4j 2.5.1 org.springframework.boot spring-boot-starter-thymeleaf javax.servlet javax.servlet-api 3.1.0 provided war org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 seasgame org.apache.maven.plugins maven-compiler-plugin 2.3.2 ${project.build.sourceEncoding} 1.7 1.7 org.apache.maven.plugins maven-surefire-plugin true

@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 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{ /** * * 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的响应方法了。一般执行以下流程

获取一个EntityManager实例

调用实例的方法createQuery,创建一个Query实例,如果有需要可以指定检索的最大数量和起始位置

使用Query方法getResultList执行查询,当然更新和删除操作得使用executeUpdate执行

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

public Page 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 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 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 entry:params.entrySet()) { query.setParameter(entry.getKey(),entry.getValue()); } query.setFirstResult((int) pageable.getOffset()); query.setMaxResults(pageable.getPageSize()); List rankEntities = query.getResultList(); Page 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@Datapublic 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,JpaSpecificationExecutor{}

动态查询

public Page getTeacherClassStudent(int pageNumber,int pageSize,int gradeId, int classId,String keyword) { pageNumber = pageNumber < 0 ? 0 : pageNumber; pageSize = pageSize < 0 ? 10 : pageSize; Specification specification = new Specification() { @Override public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { //page : 0 开始, limit : 默认为 10 List 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 pages = studentDao.findAll(specification,page); return pages; }

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

断,成立就add进去。

感谢各位的阅读!关于"怎么实现JPA多条件复杂SQL动态分页查询功能"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

查询 复杂 动态 条件 实体 对象 方法 实例 功能 查询功能 内容 接口 更多 标准 标准查询 模型 篇文章 不错 头疼 实用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 职高计算机网络技术创业方向 单机版软件开发多少钱 网络安全小报手抄报图片 一等奖 软件开发质量保障措施及计划 华为od软件开发面试 用户行为日志存放在数据库 数据库如何导入另一个服务器 中信银行软件开发中心的关系 数据库的结构被划分为哪三个层次 辽宁口碑好服务器机柜 南昌市金泉网络技术 中山市中天互联网络科技有限公司 增值产品软件开发招聘 网络技术兼职的软件 上海甄羿网络技术有限公司 2u服务器改塔式 网贷数据库怎么查询安全么 数据库超长怎么储存 nsa网络安全吗 防疫软件开发调研 信创服务器安装mysql 面试你对网络安全的理解 网络安全应用 协议 论文 软件开发支付阶段 在哪出售二手服务器 服务器root账号是什么 备份还原数据库改名 小学网络安全主题活动美文 鹰潭绿盟网络安全技术有限公司 金蝶kis云数据库
0