基于spring data jpa封装带有动态分页查询、动态条件求和的基础service类和基础controller类

基于spring data jpa封装带有动态分页查询、动态条件求和的基础service类和基础controller类

本文章介绍的是封装一个带有动态条件分页查询和动态条件求和基类
项目:springBoot项目
前提条件:引入spring data jpa依赖

源码地址:https://github.com/lizhongxiang12138/eurekaManage

代码结构

│  .gitignore
│  build.sh
│  demo.iml
│  dev-product.release
│  Dockerfile
│  eureka-mannage-deployment.yaml
│  eureka-mannage-service.yaml
│  HELP.md
│  mvnw
│  mvnw.cmd
│  pom.xml
│  README.md
│
├─.idea
│  │  compiler.xml
│  │  encodings.xml
│  │  misc.xml
│  │  modules.xml
│  │  uiDesigner.xml
│  │  vcs.xml
│  │  workspace.xml
│  │
│  ├─inspectionProfiles
│  │      Project_Default.xml
│  │
│  └─libraries
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─lzx
    │  │          └─demo
    │  │              │  DemoApplication.java --> 启动类
    │  │              │
    │  │              ├─annotation
    │  │              │      LzxLockDistributed.java
    │  │              │
    │  │              ├─aop
    │  │              │      MethodLockAop.java
    │  │              │
    │  │              ├─base
    │  │              │  │  ClassHelper.java
    │  │              │  │
    │  │              │  ├─bo
    │  │              │  │      ClassTypeBo.java
    │  │              │  │      ColumnConditionBO.java
    │  │              │  │
    │  │              │  ├─controller
    │  │              │  │      BaseController.java -->Controller基类
    │  │              │  │
    │  │              │  └─service
    │  │              │      │  BaseService.java --> Service基类接口
    │  │              │      │
    │  │              │      └─impl
    │  │              │              BaseServiceImpl.java --> Service基类实现
    │  │              │
    │  │              ├─config
    │  │              │      RepositoryConfig.java
    │  │              │
    │  │              ├─configuration
    │  │              │      ActuatorWebSecurityConfigurationAdapter.java
    │  │              │      RedisLockConfiguration.java
    │  │              │      Swagger.java
    │  │              │      ThreadPoolConfig.java
    │  │              │
    │  │              ├─controller
    │  │              │      RedisLockTestController.java
    │  │              │      StudentController.java  -- >基类测试用的controller
    │  │              │      TestController.java
    │  │              │
    │  │              ├─Dao
    │  │              │      StudentDao.java --> 基类测试用的dao
    │  │              │
    │  │              ├─dto
    │  │              │      ApplicationDTO.java
    │  │              │      ApplicationsDTO.java
    │  │              │      DataCenterInfoDTO.java
    │  │              │      InstanceDTO.java
    │  │              │      KafkaMessDTO.java
    │  │              │      LeaseInfoDTO.java
    │  │              │      MetadataDTO.java
    │  │              │      PageableDTO.java
    │  │              │      PageDataDTO.java
    │  │              │      ProductProtocolDTO.java
    │  │              │
    │  │              ├─entity
    │  │              │      Student.java --> 基类测试用的实体
    │  │              │
    │  │              ├─feign
    │  │              │      SelfFeign.java
    │  │              │      SrdFeign.java
    │  │              │
    │  │              └─service
    │  │                  │  KafkaService.java
    │  │                  │  StudentService.java --> 基类测试用的service接口
    │  │                  │
    │  │                  └─impl
    │  │                          KafkaServiceImpl.java
    │  │                          StudentServiceImpl.java --> 基类测试用的service实现
    │  │
    │  └─resources
    │      │  application.yml
    │      │  bootstrap.yml
    │      │
    │      ├─static
    │      │      apps.html
    │      │      testSendToKafka-ui.html
    │      │
    │      └─templates
    └─test
        └─java
            └─com
                └─lzx
                    └─demo
                        │  DemoApplicationTests.java
                        │
                        └─service
                            └─impl
                                    KafkaServiceImplTest.java

添加依赖

        <!-- 数据库相关 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.42</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>

数据库配置

server:
  port: ${server-port}

eureka:
  client:
    fetch-registry: true
    register-with-eureka: ${register-with-eureka}     # 是否注册到eureka
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  instance:
    prefer-ip-address: false
    hostname: ${instance-hostname}


spring:
  kafka:
    bootstrap-servers: 39.100.73.134:9092     #Kafka服务端地址
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
  profiles:
    active: dev
  redis:
    port: 6379
    host: 39.100.132.241
    password: 123456


  ######################################################
  #   数据库连接相关配置
  ######################################################
  datasource:
    url: jdbc:mysql://39.100.132.241:3306/eureka_manage?autoReconnect=true&amp;characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5Dialect



创建一个实体模型,方便后续测试

package com.lzx.demo.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.math.BigDecimal;

/**
 * 描述: 学生类
 *
 * @Auther: lzx
 * @Date: 2019/7/11 15:39
 */
@Entity(name = "STUDENT")
@Getter
@Setter
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class Student {

    /**
     * 主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Column(name = "ID",length = 32)
    private String id;

    /**
     * 名称
     */
    @Column(name = "NAME",length = 100)
    private String name;

    /**
     * 性别
     */
    @Column(name = "GENDER",length = 8)
    @Enumerated(EnumType.STRING)
    private Gender gender;
    @Getter
    @AllArgsConstructor
    public enum Gender{
        WOMAN("女"),
        MAN("男");
        private String code;
    }

    /**
     * 分数
     */
    @Column(name = "SCORE",precision = 10,scale = 5)
    private BigDecimal score;
}

创建实体模型DAO接口

package com.lzx.demo.Dao;

import com.lzx.demo.entity.Student;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.Repository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

/**
 * 描述: 学生类dao接口
 *
 * @Auther: lzx
 * @Date: 2019/7/11 15:52
 */
@RepositoryRestResource(path = "student")
public interface StudentDao extends Repository<Student,String>,JpaSpecificationExecutor<Student> {
}

创建BaseService和BaseServiceImpl

定义BaseService接口

package com.lzx.demo.base.service;

import org.springframework.data.domain.Page;

import java.util.Map;

/**
 * 描述:BaseService
 *
 * @Auther: lzx
 * @Date: 2019/7/11 16:10
 */
public interface BaseService<T> {

    /**
     * 根据条件分页查询,条件拼接方式为 and
     * 条件拼接方式  xx字段_xx操作
     * @param params
     * @return
     */
    Page<T> findAllPageByParams(Map<String,String> params);

    /**
     * 求和数据
     * 条件同上(分页条件查询) 注意~!!! 不需要分页属性,但是要添加统计的条件
     * 求和统计条件  xxx字段_sum = xx类型(支持BigDecimal 和 Long)
     *
     * @param params 参数
     * @return 查询条件
     */
    Map<String, Object> getSumByParams(Map<String, String> params) throws Exception;
}

实现BaseService(BaseServiceImpl)

package com.lzx.demo.base.service.impl;

import com.lzx.demo.base.ClassHelper;
import com.lzx.demo.base.bo.ClassTypeBo;
import com.lzx.demo.base.bo.ColumnConditionBO;
import com.lzx.demo.base.service.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 描述: 基础service实现
 *
 * @Auther: lzx
 * @Date: 2019/7/11 16:14
 */
@Slf4j
public class BaseServiceImpl<T> implements BaseService<T> {

    /**
     * 实现的dao
     * 需要在子类中具体注入
     */
    protected JpaSpecificationExecutor dao;

    /**
     * 实体管理类,使用统计求和查询时用到
     */
    @PersistenceContext
    private EntityManager em;

    /**
     * 类型
     */
    private Class clazz;

    /**
     * 根据条件分页查询,条件拼接方式为 and
     * 条件拼接方式  xx字段_xx操作,比如等于查询 xxx_eq=xxx
     * 具体操作符查看 ColumnConditionBO
     * @param params
     * @return
     */
    @Override
    public Page<T> findAllPageByParams(Map<String,String> params){
        Specification<T> specification = this.getSpecification(params);
        return dao.findAll(specification, getPageable(params));
    }

    /**
     * 求和数据
     * 条件同上(分页条件查询) 注意~!!! 不需要分页属性,但是要添加统计的条件
     * 求和统计条件  xxx字段_sum = xx类型(支持BigDecimal 和 Long)
     *
     * @param params 参数
     * @return 查询条件
     */
    public Map<String, Object> getSumByParams(Map<String, String> params) throws Exception {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Tuple> query = cb.createTupleQuery();
        clazz = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Root<T> root = query.from(clazz);

        List<Predicate> predicateListNew = getPredicateList(params,cb,root);

        Predicate[] pred = new Predicate[predicateListNew.size()];
        pred = predicateListNew.toArray(pred);


        query.where(pred);
        Set<String> keySet = params.keySet();
        List<Selection<?>> selections = new ArrayList<Selection<?>>();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            if (key.contains("_sum")) {
                if ("BigDecimal".equals(params.get(key))) {
                    selections.add(cb.sum(root.get(key.split("_")[0]).as(BigDecimal.class)));
                } else {
                    selections.add(cb.sum(root.get(key.split("_")[0]).as(Long.class)));
                }
            }
        }
        query.multiselect(selections);
        TypedQuery<Tuple> q = em.createQuery(query);
        List<Tuple> result = q.getResultList();
        Tuple tuple = result.get(0);
        Map<String, Object> param = new HashMap<>();
        int i = 0;
        Iterator<String> resultParam = keySet.iterator();
        while (resultParam.hasNext()) {
            String key = resultParam.next();
            if (key.contains("_sum")) {
                param.put(key, tuple.get(i));
                i++;
            }
        }
        return param;
    }

    /**
     * 获取查询所需要的参数
     * @param params
     * @return
     */
    private Specification<T> getSpecification(Map<String,String> params) {
        return  ((root, query, criteriaBuilder) -> {
            List<Predicate> predicateList = this.getPredicateList(params,criteriaBuilder,root);
            Predicate[] p = new Predicate[predicateList.size()];
            return criteriaBuilder.and(predicateList.toArray(p));
        });
    }


    /**
     * 获取分页属性
     * @param map
     * @return
     */
    private Pageable getPageable(Map<String, String> map) {
        int page;
        int size;
        try {
            page = Integer.parseInt(map.get("page")) - 1;
            size = Integer.parseInt(map.get("size"));
        } catch (Exception e) {
            log.error(e.getMessage());
            page = 0;
            size = 20;
        }
        String sortString = map.get("sort");
        if (null == sortString) {
            return PageRequest.of(page, size);
        } else {
            List<Sort.Order> orderList=new ArrayList<>();
            String[] columnAndDirections=sortString.split(";");
            for(int i=0;i<columnAndDirections.length;i++){
                String[] columnAndDirection = columnAndDirections[i].split(",");
                Sort.Order order=new Sort.Order(Sort.Direction.valueOf(columnAndDirection[1]),columnAndDirection[0]);
                orderList.add(order);
            }
            return PageRequest.of(page, size, Sort.by(orderList));
        }
    }

    /**
     * 查询条件扩展
     * @return
     */
    public List<Predicate> createPredicateList(){
        return new ArrayList<Predicate>();
    }

    /**
     * 获取predicateList
     * @param map
     * @return
     */
    private List<Predicate> getPredicateList(Map<String,String> map, CriteriaBuilder cb, Root<T> root){
        List<Predicate> predicateList = new ArrayList<>();
        map.forEach((k, v) -> {
            try {
                ColumnConditionBO columnConditionBO = ColumnConditionBO.parse(k);
                Predicate predicate=this.getPredicate(columnConditionBO, v, cb, root);
                if(predicate==null){
                    log.warn(k+"查询条件错误");
                }else{
                    predicateList.add(predicate);
                }

            } catch (Exception e) {
                log.error(e.getMessage());
            }
        });
        return predicateList;
    }

    /**
     * 获取查询
     *
     * @param columnConditionBO 字段、条件业务类
     * @param value             查询值
     * @param criteriaBuilder   cb
     * @param root              root
     * @return 查询条件
     */
    private Predicate getPredicate(ColumnConditionBO columnConditionBO, String value, CriteriaBuilder criteriaBuilder, Root<T> root) throws NoSuchFieldException {
        //获取查询字段的类型,fieldClass为查询类中字段的类型,classType为根据类型定义的枚举类
        clazz = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        while (clazz!=null){
            try{
                //对于子类无法获取父类的私有属性,需要递归向上获取父类的私有属性
                Field field = ClassHelper.getDeclaredField(clazz, columnConditionBO.getColumn());
                Class fieldClass = field.getType();
                //判断fieldClass是否是枚举类
                if (!fieldClass.isEnum()) {
                    return basicPredicate(columnConditionBO, value, criteriaBuilder, root, fieldClass);
                } else {
                    return enumPredicate(columnConditionBO, value, criteriaBuilder, root, fieldClass.getEnumConstants());
                }
            }catch (Exception e){
                log.error(e.getMessage());
                clazz=clazz.getSuperclass();
            }
        }
        String noSuchFieldException="根据查询参数获取类中的域失败";
        log.warn(noSuchFieldException);
        throw new NoSuchFieldException(noSuchFieldException);
    }

    /**
     * 基础类predicate生成方法
     *
     * @param columnConditionBO 参数条件
     * @param value             查询条件值
     * @param criteriaBuilder   构建起
     * @param root              root
     * @param fieldClass        fieldClass
     * @return predicate
     */
    private Predicate basicPredicate(ColumnConditionBO columnConditionBO, String value, CriteriaBuilder criteriaBuilder, Root<T> root, Class fieldClass) {
        ClassTypeBo classType = ClassTypeBo.valueOf(fieldClass.getSimpleName());
        switch (columnConditionBO.getCondition()) {
            case lk: {
                return criteriaBuilder.like(root.get(columnConditionBO.getColumn()), value);
            }case sw: {
                return criteriaBuilder.like(root.get(columnConditionBO.getColumn()), value + "%");
            }case ew: {
                return criteriaBuilder.like(root.get(columnConditionBO.getColumn()), "%" + value);
            }case containing: {
                return criteriaBuilder.like(root.get(columnConditionBO.getColumn()), "%" + value + "%");
            }case eq: {
                return criteriaBuilder.equal(root.get(columnConditionBO.getColumn()), value);
            }case not:{
                return criteriaBuilder.notEqual(root.get(columnConditionBO.getColumn()), value);
            }case isNull:{
                return criteriaBuilder.isNull(root.get(columnConditionBO.getColumn()));
            }case isNotNull:{
                return criteriaBuilder.isNotNull(root.get(columnConditionBO.getColumn()));
            }case between: {
                String[] minAndMax = value.split(",");
                switch (classType) {
                    case LocalDateTime: {
                        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
                        return criteriaBuilder.between(root.get(columnConditionBO.getColumn()), LocalDateTime.parse(minAndMax[0], dateTimeFormatter), LocalDateTime.parse(minAndMax[1], dateTimeFormatter));
                    }case String: {
                        return criteriaBuilder.between(root.get(columnConditionBO.getColumn()), minAndMax[0], minAndMax[1]);
                    }case Integer: {
                        return criteriaBuilder.between(root.get(columnConditionBO.getColumn()), Integer.parseInt(minAndMax[0]), Integer.parseInt(minAndMax[1]));
                    }case Long: {
                        return criteriaBuilder.between(root.get(columnConditionBO.getColumn()), Long.parseLong(minAndMax[0]), Long.parseLong(minAndMax[1]));
                    }case BigDecimal: {
                        return criteriaBuilder.between(root.get(columnConditionBO.getColumn()), new BigDecimal(minAndMax[0]), new BigDecimal(minAndMax[1]));
                    }case Date:{
                        SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                        try {
                            return criteriaBuilder.between(root.get(columnConditionBO.getColumn()), dateTimeFormatter.parse(minAndMax[0]),dateTimeFormatter.parse(minAndMax[1]));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }default:
                        return null;
                }
            }case ge:{
                switch (classType){
                    case Date:{
                        SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                        try {
                            return criteriaBuilder.greaterThanOrEqualTo(root.get(columnConditionBO.getColumn()), dateTimeFormatter.parse(value));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }default:{
                        return criteriaBuilder.greaterThanOrEqualTo(root.get(columnConditionBO.getColumn()), value);
                    }
                }
            }case gt:{
                switch (classType){
                    case Date:{
                        SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                        try {
                            return criteriaBuilder.greaterThan(root.get(columnConditionBO.getColumn()), dateTimeFormatter.parse(value));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }default:{
                        return criteriaBuilder.greaterThanOrEqualTo(root.get(columnConditionBO.getColumn()), value);
                    }
                }
            }case le:{
                switch (classType){
                    case Date:{
                        SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                        try {
                            return criteriaBuilder.lessThanOrEqualTo(root.get(columnConditionBO.getColumn()), dateTimeFormatter.parse(value));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }default:{
                        return criteriaBuilder.greaterThanOrEqualTo(root.get(columnConditionBO.getColumn()), value);
                    }
                }
            }case lt:{
                switch (classType){
                    case Date:{
                        SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                        try {
                            return criteriaBuilder.lessThan(root.get(columnConditionBO.getColumn()), dateTimeFormatter.parse(value));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }default:{
                        return criteriaBuilder.greaterThanOrEqualTo(root.get(columnConditionBO.getColumn()), value);
                    }
                }
            }case in: {
                String[] inValues = value.split(",");
                List<String> stringList = Arrays.asList(inValues);
                switch (classType) {
                    case LocalDateTime: {
                        CriteriaBuilder.In<LocalDateTime> in = criteriaBuilder.in(root.get(columnConditionBO.getColumn()));
                        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
                        stringList.forEach(s -> in.value(LocalDateTime.parse(s, dateTimeFormatter)));
                        return in;
                    }case String: {
                        CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get(columnConditionBO.getColumn()));
                        stringList.forEach(in::value);
                        return in;
                    }case Long: {
                        CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get(columnConditionBO.getColumn()));
                        stringList.forEach(s -> in.value(Long.parseLong(s)));
                        return in;
                    }case BigDecimal: {
                        CriteriaBuilder.In<BigDecimal> in = criteriaBuilder.in(root.get(columnConditionBO.getColumn()));
                        stringList.forEach(s -> in.value(new BigDecimal(s)));
                        return in;
                    }case Integer: {
                        CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get(columnConditionBO.getColumn()));
                        stringList.forEach(s -> in.value(Integer.parseInt(s)));
                        return in;
                    }default: {
                        return null;
                    }
                }
            }default: {
                return null;
            }
        }
    }

    /**
     * enum类predicate生成方法
     *
     * @param columnConditionBO 参数条件
     * @param value             查询值
     * @param criteriaBuilder   构建起
     * @param root              root
     * @param ys                ys
     * @return predicate
     */
    private <Y> Predicate enumPredicate(ColumnConditionBO columnConditionBO, String value, CriteriaBuilder criteriaBuilder, Root<T> root, Y[] ys) {
        //枚举类型处理
        CriteriaBuilder.In<Y> in = criteriaBuilder.in(root.get(columnConditionBO.getColumn()));
        Arrays.asList(value.split(",")).forEach(s -> Arrays.asList(ys).forEach(f -> {
            if (f.toString().equals(s)) {
                in.value(f);
            }
        }));
        return in;
    }

}

创建BaseController

package com.lzx.demo.base.controller;

import com.lzx.demo.base.service.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Map;

/**
 * 描述: BaseController
 *
 * @Auther: lzx
 * @Date: 2019/7/11 17:03
 */
@Slf4j
public class BaseController<T> {

    /**
     * 需要在子类中具体注入
     */
    protected BaseService baseService;

    /**
     * 根据条件分页查询,条件拼接方式为 and
     * 条件拼接方式  xx字段_xx操作
     * @param parameters
     * @return
     */
    @GetMapping("/findAllPageByParams")
    public Page<T> findAllPageByParams(@RequestParam Map<String, String> parameters) {
        return baseService.findAllPageByParams(parameters);
    }

    /**
     * 求和数据
     * 条件同上(分页条件查询) 注意~!!! 不需要分页属性,但是要添加统计的条件
     * 求和统计条件  xxx字段_sum = xx类型(支持BigDecimal 和 Long)
     *
     * @param params 参数
     * @return 查询条件
     */
    @GetMapping("/getSumByParams")
    public Map<String, Object> getSumByParams(@RequestParam Map<String, String> params) throws Exception {
        return baseService.getSumByParams(params);
    }

}

使用

service使用

接口继承BaseService

package com.lzx.demo.service;

import com.lzx.demo.base.service.BaseService;
import com.lzx.demo.entity.Student;

/**
 * 描述: 学生类service接口
 *
 * @Auther: lzx
 * @Date: 2019/7/11 17:08
 */
public interface StudentService extends BaseService<Student> {
}

实现类继承BaseServiceImpl

package com.lzx.demo.service.impl;

import com.lzx.demo.Dao.StudentDao;
import com.lzx.demo.base.service.impl.BaseServiceImpl;
import com.lzx.demo.entity.Student;
import com.lzx.demo.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.List;

/**
 * 描述:
 *
 * @Auther: lzx
 * @Date: 2019/7/11 17:09
 */
@Service
@Slf4j
public class StudentServiceImpl extends BaseServiceImpl<Student> implements StudentService {

    private StudentDao studentDao;

    public StudentServiceImpl(StudentDao studentDao) {
        /*
            !!!!!!!!!!!!!!!!!!!!重点:
            这个时必须的   ·······~~~~~~~~注意哦
         */
        this.dao = studentDao;
        this.studentDao = studentDao;
    }

    /**
     * 扩展基类中没有的查询条件自己的查询条件
     * @return
     */
    @Override
    public List<Predicate> createPredicateList() {
        return super.createPredicateList();
    }
}

controller使用

package com.lzx.demo.controller;

import com.lzx.demo.base.controller.BaseController;
import com.lzx.demo.entity.Student;
import com.lzx.demo.service.StudentService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 描述: 学生api
 *
 * @Auther: lzx
 * @Date: 2019/7/11 17:14
 */
@RestController
@RequestMapping("/student")
public class StudentController extends BaseController<Student> {

    private StudentService studentService;

    public StudentController(StudentService studentService) {
         /*
            !!!!!!!!!!!!!!!!!!!!重点:
            这个时必须的   ·······~~~~~~~~注意哦
         */
        this.baseService = studentService;
        this.studentService = studentService;
    }
}

最后看效果,启动项目

使用postman调用接口

分页的条件查询
基于spring data jpa封装带有动态分页查询、动态条件求和的基础service类和基础controller类
根据条件求和查询
基于spring data jpa封装带有动态分页查询、动态条件求和的基础service类和基础controller类

上一篇:JPA 动态查询之AND、OR结合使用


下一篇:Java常用函数式接口--Consumer接口andThen()方法使用案例(二)