(spring boot)spring data JPA 高级动态查询, 排序加分页加多参数查询 返回二元组

(spring boot)spring data JPA 高级动态查询, 排序加分页加多参数查询 返回二元组

业务需求是根据前端传来的四个参数进行匹配查询, 并且要将总共查出来的数据总数返回至前端(因为前端有进行分页, 首尾页等), 但是前端未必会传来四个参数, 也可能是随机的其中一个,两个等. 这时候如果自己在dao层,手写查询方法或者sql语句需要大量代码, 并且非常麻烦, 在多方查阅资料,以及询问公司前辈的情况下, 终于完成了项目需求,
贴出前端查询页面:贴出前端查询页面
先贴出二元组的代码,

package com.leadmap.mapservice.common;

/**
 * Company: 
 * Description:
 *
 * @author: ljy
 * @Date: 2019/1/3 15:27
 */
	public class TwoTuple {
   	public final A first;
    private final B second;
    
    public TwoTuple(A a, B b){
        first = a;
        second = b;
    }

    public A getFirst() {
        return first;
    }

    public B getSecond(){
        return second;
    }

    @Override
    public String toString(){
        return "(" + first + ", " + second + ")";
    }
}

controller层代码:

package com.leadmap.mapservice.controller;

import com.leadmap.mapservice.common.TwoTuple;
import com.leadmap.mapservice.dao.DocumentInfoDao;
import com.leadmap.mapservice.dao.OpinionFeedbackDao;
import com.leadmap.mapservice.dao.UserCollectDocDao;
import com.leadmap.mapservice.dao.UserLikeDocDao;
import com.leadmap.mapservice.dto.ResultInfo;
import com.leadmap.mapservice.entity.DocumentInfo;
import com.leadmap.mapservice.entity.OpinionFeedback;
import com.leadmap.mapservice.service.DocumentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Company: 
 * Description:
 *
 * @author: ljy
 * @Date: 2018/12/20 10:31
 */
@Controller
public class DocumentController {

    private final static Logger logger = LoggerFactory.getLogger(DocumentController.class);

    @Autowired
    private DocumentInfoDao documentInfoDao;

    @Autowired
    private OpinionFeedbackDao opinionFeedbackDao;

    @Autowired
    private DocumentService documentService;

    @ResponseBody
    @RequestMapping(value = "/documentList", method = RequestMethod.POST)
    public ResultInfo> getAll(HttpServletRequest request){
        ResultInfo>  resultInfo = new ResultInfo<>();
        int pageNum = Integer.valueOf(request.getParameter("pageNum"));
        String beginTime = request.getParameter("beginTime");
        String endTime = request.getParameter("endTime");
        String type = request.getParameter("type");
        String title = request.getParameter("title");
        TwoTuple, Integer> tuple = documentService.getPageDocumentInfo(pageNum,10, beginTime, endTime, type, title);
        resultInfo.setCode("200");
        resultInfo.setMsg("success");
        resultInfo.setData(tuple.getFirst());
        resultInfo.setRecordCount(tuple.getSecond());
        return resultInfo;
    }
}

业务(service)层代码:

package com.leadmap.mapservice.service;

import com.leadmap.mapservice.common.TwoTuple;
import com.leadmap.mapservice.common.Util;
import com.leadmap.mapservice.dao.DocumentInfoDao;
import com.leadmap.mapservice.dao.OpinionFeedbackDao;
import com.leadmap.mapservice.entity.DocumentInfo;
import com.leadmap.mapservice.entity.OpinionFeedback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Company: 
 * Description:
 *
 * @author: ljy
 * @Date: 2018/12/28 9:17
 */
@Service
 public class DocumentService {

    	@Autowired
    	private DocumentInfoDao documentInfoDao;

    	@Autowired
    	private OpinionFeedbackDao opinionFeedbackDao;
		
		// 返回结果为实体类对象数组和匹配数据总数
		// 两个日期参数格式为 yyyy-MM-dd  数据库中对应字段格式为yyyy-mm-dd hh-mm-ss 因此下面会进行日期字符串拼接
    	public TwoTuple, Integer> getPageDocumentInfo(int start, int count, String beginTime, String endTime, String type, String title){
    	// 创建分页参数
        Pageable page = new PageRequest(start, count);
        List list = new ArrayList<>();
        // 新建查询参数, 重写方法
        Specification querySpecifi = new Specification() {
        	// 这几个参数算是固定用法吧 要用到就写上去 
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
            	// 姑且叫做 新建查询参数数组吧, 是多个查询条件组合的的数组 
                List predicatesList = new ArrayList<>();
                // 当if成立 添加 匹配大于开始时间的查询参数
                if(!beginTime.isEmpty()){
                    Date beginDate = Util.StrToDate(beginTime+" 00:00:00");
                    predicatesList.add(criteriaBuilder.greaterThan(root.get("createTime"), beginDate));
                }
                // 同上 添加 匹配小于开始时间的查询参数  这两个参数组合也就相当于sql中的between...and...
                if(!endTime.isEmpty()){
                    Date endDate = Util.StrToDate(endTime + " 00:00:00");
                    predicatesList.add(criteriaBuilder.lessThan(root.get("createTime"), endDate));
                }
                // 添加匹配数据库中相同类型的参数
                if(!type.isEmpty()){
                    predicatesList.add(criteriaBuilder.like(root.get("type"),"%"+type+"%"));
                }
                
                if(!title.isEmpty()){
                    predicatesList.add(criteriaBuilder.like(root.get("title"), "%" + title + "%"));
                }
                // 设置排序条件 根据id倒序
                criteriaQuery.orderBy(criteriaBuilder.desc(root.get("id")));
                // 将排序与添加好的查询参数数组 作为返回值
                criteriaQuery.where(criteriaBuilder.and(predicatesList.toArray(new Predicate[predicatesList.size()])));
                return criteriaQuery.getRestriction();
            }
        };
        // 这个findAll是JpaSpecificationExecutor接口的方法
        list = documentInfoDao.findAll(querySpecifi,page).getContent();
        // 拿到 匹配数据总数 此处以每页十条分页
        Integer counts = documentInfoDao.findAll(querySpecifi).size() / 10;
        // 返回二元组
        return new TwoTuple, Integer>(list, counts);
    }

    public List getPageOpinionFeedbackInfo(int start, int count){
        Pageable page = new PageRequest(start,count);
        return opinionFeedbackDao.findAllByOrderByIdDesc(page);
    }
}

dao层代码:

@Repository
public interface DocumentInfoDao extends PagingAndSortingRepository, JpaSpecificationExecutor {

    /**
     * 根据id查找
     *
     * @param id
     * @return
     */
    DocumentInfo findById(Long id);
}

dto(数据传输)层代码:

package com.leadmap.mapservice.dto;

import java.io.Serializable;

/**
 * Company:
 * Description:
 *
 * @author: ljy
 * @Date: 2018/12/28 15:26
 */
public class ResultInfo implements Serializable {

    private String code;

    private String msg;

    private T data;

    private long recordCount;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public long getRecordCount() {
        return recordCount;
    }

    public void setRecordCount(long recordCount) {
        this.recordCount = recordCount;
    }

}

实体类层代码很多 看到这的朋友如果对查询条件还是有一点疑问就看看, 否则大可跳过
entity(实体类)层代码:

package com.leadmap.mapservice.entity;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
 * Company: 
 * Description:
 *
 * @author: ttq
 * @Date: 2018/7/17 11:15
 */
@MappedSuperclass
public abstract class IdEntity implements Serializable {
    public IdEntity() {
        createTime = new Date();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "createTime")
    protected Date createTime;

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}
package com.leadmap.mapservice.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;

/**
 * Company: 
 * Description:
 *
 * @author: ljy
 * @Date: 2018/12/20 10:34
 */
@Entity
@Table(name="documentInfo")
public class DocumentInfo extends IdEntity implements Serializable {

    @Column(name = "content")
    private String content;

    /**
     * 文章url
     */
    @Column(name = "documentUrl")
    private String documentUrl;

    /**
     * 图片url
     */
    @Column(name = "imageUrl")
    private String imageUrl;

    /**
     * 发表日期
     */
    @Column(name="publishDate")
    private String publishDate;

    /**
     * 出版人
     */
    @Column(name = "publisher")
    private String publisher;

    /**
     * 文章标题
     */
    @Column(name = "title")
    private String title;

    /**
     * 类型
     */
    @Column(name = "type")
    private String type;

    public void setContent(String content) {
        this.content = content;
    }

    public void setDocumentUrl(String documentUrl) {
        this.documentUrl = documentUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public void setPublishDate(String publishDate) {
        this.publishDate = publishDate;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getContent() {

        return content;
    }

    public String getDocumentUrl() {
        return documentUrl;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public String getPublishDate() {
        return publishDate;
    }

    public String getPublisher() {
        return publisher;
    }

    public String getTitle() {
        return title;
    }

    public String getType() {
        return type;
    }
}

差不多到这里 结束了 博主也是新手, 如果还有不懂得欢迎讨论交流.

你可能感兴趣的:(Java)