• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • SpringBoot JPA使用Specification多條件查詢(精確查詢、模糊查詢、時間段查詢)及分頁

    標簽: springboot  JPA

    1.實體類Mobile

    package com.frank.jpaSpecification.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import java.time.LocalDate;
    
    /**
     * @author 小石潭記
     * @date 2020/10/4 14:14
     * @Description: ${todo}
     */
    @Entity
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Table(name = "t_mobile")
    public class Mobile {
    
        @Id
        @GeneratedValue
        private Integer id;
    
        private String name;
    
        private String branch;
    
        private String address;
    
        private Double price;
    
        private LocalDate createTime;
    
    }
    

    2.MobileRepository,注意需要基礎JpaSpecificationExecutor

    package com.frank.jpaSpecification.repository;
    
    import com.frank.jpaSpecification.entity.Mobile;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.data.repository.PagingAndSortingRepository;
    import org.springframework.stereotype.Component;
    
    /**
     * @author 小石潭記
     * @date 2020/12/12 14:21
     * @Description: ${todo}
     */
    @Component
    public interface MobileRepository extends PagingAndSortingRepository<Mobile, Integer>, JpaSpecificationExecutor<Mobile> {
    }
    

    3.PageParamRequest請求參數體

    package com.frank.jpaSpecification.entity;
    
    import lombok.Data;
    import org.springframework.format.annotation.DateTimeFormat;
    
    import java.time.LocalDate;
    import java.util.List;
    
    /**
     * @author 小石潭記
     * @date 2020/12/12 14:26
     * @Description: ${todo}
     */
    @Data
    public class PageParamRequest {
        private Integer pageSize = 10;
        private Integer pageNumber = 1;
        private String searchName;
        private String searchBranch;
        private String searchId;
        private List<Double> priceList;
    
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate startTime;
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate endTime;
    
    }
    

    4.MobileService

    package com.frank.jpaSpecification.service;
    
    import com.frank.jpaSpecification.entity.Mobile;
    import com.frank.jpaSpecification.entity.PageParamRequest;
    import com.frank.jpaSpecification.repository.MobileRepository;
    import com.frank.jpaSpecification.specification.MobileSpecification;
    import com.google.common.collect.Lists;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /**
     * @author 小石潭記
     * @date 2020/12/12 14:22
     * @Description: ${todo}
     */
    @Service
    public class MobileService {
    
        @Autowired
        private MobileRepository mobileRepository;
    
        @Autowired
        private MobileSpecification mobileSpecification;
    
        public Page<Mobile> getAllMobile(PageParamRequest pageParamRequest) {
            // 根據價格降序
            Sort sort = new Sort(Sort.Direction.DESC, "createTime");
            PageRequest pageRequest = PageRequest.of(pageParamRequest.getPageNumber(), pageParamRequest.getPageSize(), sort);
            return mobileRepository.findAll(mobileSpecification.getMobileSpecification(pageParamRequest), pageRequest);
        }
    
    }
    

    5.MobileSpecification

    package com.frank.jpaSpecification.specification;
    
    import com.frank.jpaSpecification.entity.Mobile;
    import com.frank.jpaSpecification.entity.PageParamRequest;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.data.jpa.domain.Specification;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    
    import javax.persistence.criteria.Predicate;
    import java.time.LocalDate;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author 小石潭記
     * @date 2020/12/12 14:27
     * @Description: ${todo}
     */
    @Component
    public class MobileSpecification {
    
        /**
         * root 就是mobile實例  root.get("name") name是屬性名 不是數據庫字段名
         * @param paramRequest
         * @return
         * */
        public Specification<Mobile> getMobileSpecification(PageParamRequest paramRequest) {
            return (root, criteriaQuery, criteriaBuilder) -> {
                List<Predicate> list = new ArrayList<>();
    
                String searchName = paramRequest.getSearchName();
    
                if (StringUtils.isNotBlank(searchName)) {
                    list.add(criteriaBuilder.like(root.get("name").as(String.class), "%" + searchName + "%"));
                }
    
                String searchId = paramRequest.getSearchId();
                if (StringUtils.isNotBlank(searchId)) {
                    list.add(criteriaBuilder.equal(root.get("id").as(Long.class), searchId));
                }
    
                // 模糊查詢
                String searchBranch = paramRequest.getSearchBranch();
                if (StringUtils.isNotBlank(searchBranch)) {
                    list.add(criteriaBuilder.like(root.get("branch").as(String.class), "%" + searchBranch + "%"));
                }
    
                // 前端傳遞價格列表,查詢在列表里面的數據 in
                List<Double> priceList = paramRequest.getPriceList();
                if (!CollectionUtils.isEmpty(priceList)) {
                    list.add(criteriaBuilder.and(root.get("price").as(Double.class).in(priceList)));
                }
    
                // 時間范圍
                LocalDate startTime = paramRequest.getStartTime();
                LocalDate endTime = paramRequest.getEndTime();
                //起始日期
                if (startTime != null && !startTime.equals("")) {
                    list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDate.class), startTime));
                }
                //結束日期
                if (endTime != null && !endTime.equals("")) {
                    list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDate.class), endTime));
                }
    
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            };
        }
    
    }
    

    6.MobileController

    package com.frank.jpaSpecification.controller;
    
    import com.frank.jpaSpecification.entity.Mobile;
    import com.frank.jpaSpecification.entity.PageParamRequest;
    import com.frank.jpaSpecification.service.MobileService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author 小石潭記
     * @date 2020/12/12 14:24
     * @Description: ${todo}
     */
    @RestController
    @RequestMapping("/mobile")
    public class MobileController {
    
        @Autowired
        private MobileService mobileService;
    
        /**
         * 注意這里是從0頁開始查詢的
         * @param request
         * @return
         */
        @GetMapping("/list")
        public Page<Mobile> getAllMobileList(PageParamRequest request) {
            return mobileService.getAllMobile(request);
        }
    
    }
    

    7.測試 

    http://localhost:8080/mobile/list?searchId=&searchBranch=華為&searchName&pageNumber=0&pageSize=5&priceList=6999,2999&startTime=2019-01-01&endTime=2020-01-01

     

    修改請求參數,測試結果正確。以上就完成了使用jap單表的復雜查詢和分頁。

    sql數據:

    -- --------------------------------------------------------
    -- 主機:                           127.0.0.1
    -- 服務器版本:                        5.6.40 - MySQL Community Server (GPL)
    -- 服務器操作系統:                      Win64
    -- HeidiSQL 版本:                  8.2.0.4675
    -- --------------------------------------------------------
    
    /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
    /*!40101 SET NAMES utf8 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    
    -- 導出 test 的數據庫結構
    CREATE DATABASE IF NOT EXISTS `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */;
    USE `test`;
    
    
    -- 導出  表 test.t_mobile 結構
    CREATE TABLE IF NOT EXISTS `t_mobile` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `address` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
      `branch` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
      `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
      `price` double DEFAULT NULL,
      `create_time` date DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
    
    -- 正在導出表  test.t_mobile 的數據:~11 rows (大約)
    DELETE FROM `t_mobile`;
    /*!40000 ALTER TABLE `t_mobile` DISABLE KEYS */;
    INSERT INTO `t_mobile` (`id`, `address`, `branch`, `name`, `price`, `create_time`) VALUES
    	(1, '成都', '華為', '華為mete40', 6999, '2010-10-12'),
    	(2, '北京', '小米', '小米10青春版', 2999, '2017-05-04'),
    	(3, '成都', '華為', '華為mete30', 6399, '2018-06-06'),
    	(4, '廣東', '蘋果', '蘋果12max', 8999, '2020-12-12'),
    	(5, '成都', '華為', '華為mete40', 6999, '2020-10-05'),
    	(6, '重慶', '紅米', '紅米K30', 1999, '2020-04-08'),
    	(7, '成都', '華為', '華為mete40', 6999, '2019-08-08'),
    	(8, '深圳', '魅族', '魅族9 pro', 3299, '2019-07-08'),
    	(9, '成都', '華為', '華為mete40', 6999, '2016-05-05'),
    	(10, '上海', 'OPPO', 'OPPO A92s', 3699, '2014-03-04'),
    	(11, '成都', '華為', '華為P40', 4999, '2015-09-09');
    /*!40000 ALTER TABLE `t_mobile` ENABLE KEYS */;
    /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
    /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
    /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
    

     

     

     

    版權聲明:本文為qq_33371766原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_33371766/article/details/111083064

    智能推薦

    動態熱修復技術的實現

    原文地址為:動態熱修復技術的實現 項目地址:https://github.com/dodola/HotFix HotFix 安卓App熱補丁動態修復框架 介紹 該項目是基于QQ空間終端開發團隊的技術文章實現的,完成了文章中提到的基本功能。 文章地址:安卓App熱補丁動態修復技術介紹 項目部分代碼從 dalvik_patch 項目中修改而來,這個項目本來是用來實現multidex的,發現可以用來實現...

    初窺SpringSecurity安全框架

    文章目錄 概念 對應依賴 創建項目 自定義登陸用戶和密碼 新增SecurityConfig配置類 修改前臺配置 重啟項目驗證 登陸頁配置:記住我 退出的問題 作為一名開發怎能不知道大名頂頂的安全框架呢?市面上流行的安全框架有:shiro和springSecurity。那么你經常用哪個框架做安全訪問控制呢?因為SpringBoot集成了SpringSecurity,所以我們這次來聊聊它 概念 Spr...

    數據結構(三)——基于數組的隊列和循環隊列

        隊Queue也是一個線性的存儲結構,原則是先入先出(FIFO),區別于棧的先進后出。就類似與排隊買票,先進入隊列的就先買票出列;入隊在一端操作(隊尾),出隊只能在另一端操作(隊首);     一個隊列的基本操作就是入隊,出隊,獲取隊列大小,判斷是否為空等等;這篇博客就是自己實現一個基于數組的隊列和循環隊列。 &...

    解決“Win 10 ipv6無網絡權限/無Internet連接權限”問題

    高校校園網有一個好處就是可以自由使用ipv6上各種BT、PT,然而ipv6由于商用不廣泛,各種ipv6解決方案不規范,導致各種使用問題。我最近遇到的問題:裝完Win 10后,已經換了hosts文件,為了上goole,問題是 ipv6就出現了無網絡權限。 經過試驗,發現核心解決方案,僅僅是使用CMD或者Windows Power Shell執行網絡配置命令即可:     &nbs...

    規則引擎QLExpress

    本文從官網總結而來,并在網上摘抄了幾個核心概念的解釋(比如強弱類型、動態靜態類型)。由于摘抄的比較雜亂,這里就不一一列舉原網站了,望諒解。 摘要 QLExpress與Groovy比較 QLExpress Groovy 解析型,編譯成自定義的內存指令 編譯形,產生一個獨立的class文件 表達式語言(EL expression language) 表達式語言(EL expression langua...

    猜你喜歡

    05、隊列(queue):隊列在線程池等有限資源池中的應用

    05、|隊列(queue):隊列在線程池等有限資源池中的應用 5.1 如何理解“隊列”? 先進者先出,這就是典型的“隊列” 最基本的操作也是兩個: 入隊 enqueue(),放一個數據到隊列尾部; 出隊 dequeue(),從隊列頭部取一個元素。 實現: 用數組實現的隊列叫作順序隊列; 用鏈表實現的隊列叫作鏈式隊列。 隊列需要兩個指針: 一個是 he...

    【轉】WPF MVVM 循序漸進 (從基礎到高級) 【已翻譯100%】【2】

    原文地址:http://www.oschina.net/translate/wpf-mvvm-step-by-step-basics-to-advance-level?lang=chs&page=2# 上面的 command 代碼中,ViewModel 對象是通過構造函數傳遞進來。所以 ViewModel 類需要創建一個 command 對象來暴露這個對象的“ICommand&...

    【Python+OpenCV】目標跟蹤-卡爾曼濾波-鼠標軌跡跟蹤

    卡爾曼是匈牙利數學家,Kalman濾波器源于其博士畢業了論文和1960年發表的論文《A New Approach to Linear Filtering and Prediction Problems》(線性濾波與預測問題的新方法)。 論文地址 卡爾曼濾波算法分為兩個階段: 預測階段:卡爾曼濾波器使用由當前點計算的協方差來估計目標的新位置; 更新階段:卡爾曼濾波器記錄目標的位置,并為下一次循環計算...

    工廠方法模式FactoryMethod

    1. 定義 定義一個用于創建對象的接口,讓子類決定實例化哪一個類,FactoryMethod使一個類的實例化延遲到其子類。   2. 結構圖 Product:定義工廠方法所創建的對象的接口,也就是實際需要使用的對象的接口。 ConcreteProduct:具體的Product接口的實現對象。 Creator:創建器,聲明工廠方法,工廠方法通常會返回一個Product類型的實例對象,而且多...

    【前端規范】約定式提交

    「約定大于配置」 的思想在軟件工程領域得到了廣泛的應用,例如 Spring、Angular 等大型項目。其目的只有一個:減少軟件開發人員做決定的數量,提升開發效率。這種思想同樣被應用到 Git 提交當中,即 「約定式提交」。 什么是約定式提交? 約定式提交規范是一種基于提交消息的輕量級約定。所謂輕量級約定,說白了,就是有一套用于創建提交消息的簡單規則,這套規則源自于Angular 提交規范,規定了...

    精品国产乱码久久久久久蜜桃不卡