Spring Data JPA【JpaSpecificationExecutor】多条件动态查询简单示例

1. 表结构

CREATE TABLE `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`uid`),
  UNIQUE KEY `UK_USER_NAME` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (1, 'neau', 'neau');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (2, 'First', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (4, 'Sec', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (5, 'Sec0', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (6, 'Sec00', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (7, '11c00', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (8, '142400', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (9, '144200', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (10, '14', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (11, 'll4', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (12, 'ii', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (13, 'ii2', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (14, 'ii27', 'First');
INSERT INTO `test`.`user`(`uid`, `username`, `password`) VALUES (15, 'ii2o7', 'First');

Spring Data JPA【JpaSpecificationExecutor】多条件动态查询简单示例_第1张图片

2. 实体类 @Entity

package top.actim.springdata.pojo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;

@Entity
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int uid;
    private String username;
    private String password;

    public User() {
    }

    public User(int uid, String username, String password) {
        this.uid = uid;
        this.username = username;
        this.password = password;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

3. DAO层接口

package top.actim.springdata.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import top.actim.springdata.pojo.User;

public interface UserRepository 
extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
    // 无需写方法,JpaRepository包含基本增删改查分页等功能,JpaSpecificationExecutor包含复杂条件查询接收方法
    // 自定义规范方法
    User findByUsername(String username);
}

4. Service组合查询条件

分页、uid大于5

package top.actim.springdata.service;

import org.springframework.beans.factory.annotation.Autowired;
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.stereotype.Service;
import top.actim.springdata.dao.UserRepository;
import top.actim.springdata.pojo.User;

import javax.persistence.criteria.*;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User addNewUser(String username, String password) {
        User n = new User();
        n.setUsername(username);
        n.setPassword(password);
        userRepository.save(n);
        return n;
    }

    public Iterable<User> getAllUsers() {
        return userRepository.findAll();
    }

    public User getByUsername(String username) {
        return userRepository.findByUsername(username);
    }

    // 分页查询uid大于5的User
    public Page<User> getByUidGt5(){
        // 分页参数 降序、页码、页容量
        Sort sort = new Sort(Sort.Direction.DESC,"uid");
        int page = 1;
        int pageSize = 5;
        Pageable pageable = PageRequest.of(page,pageSize,sort);

        //通常使用 Specification(条件) 的匿名内部类
        Specification<User> specification = new Specification<User>() {
            /**
             * @param *root: 代表查询的实体类.
             * @param query: 可以从中得到 Root 对象,
             * 即告知 JPA Criteria 查询要查询哪一个实体类.
             * 还可以来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.
             * @param *cb: CriteriaBuilder 对象.
             * 用于创建 Criteria 相关对象的工厂.
             * 当然可以从中获取到 Predicate 对象
             * @return: *Predicate 类型, 代表一个查询条件.
             */
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path path = root.get("uid");// 字段
                Predicate predicate = cb.gt(path, 5);// 大于5
                return predicate;
            }
        };

        // 调用查询方法,加入条件参数、分页参数
        Page<User> userPage = userRepository.findAll(specification,  pageable);
        return userPage;
    }
}

5. Controller

package top.actim.springdata.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import top.actim.springdata.pojo.User;
import top.actim.springdata.service.UserService;

@Controller
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping(path = "/add")
    @ResponseBody
    public User addNewUser(@RequestParam String username, @RequestParam String password) {
        return userService.addNewUser(username, password);
    }

    @GetMapping(path = "/all")
    @ResponseBody
    public Iterable<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @GetMapping(path = "/name")
    @ResponseBody
    public User getUserByName(String username) {
        return userService.getByUsername(username);
    }

    @GetMapping(path = "/uid/gt5")
    @ResponseBody //测试
    public Page<User> getByUidGt5() {
        return userService.getByUidGt5();
    }

}

6. 测试

启动程序
用浏览器访问 http://localhost:8080/user/uid/gt5

{"content":[{"uid":10,"username":"14","password":"First"},{"uid":9,"username":"144200","password":"First"},{"uid":8,"username":"142400","password":"First"},{"uid":7,"username":"11c00","password":"First"},{"uid":6,"username":"Sec00","password":"First"}],"pageable":{"sort":{"sorted":true,"unsorted":false,"empty":false},"offset":5,"pageSize":5,"pageNumber":1,"paged":true,"unpaged":false},"last":true,"totalPages":2,"totalElements":10,"number":1,"size":5,"sort":{"sorted":true,"unsorted":false,"empty":false},"numberOfElements":5,"first":false,"empty":false}

7. 参考文章

Spring Data JPA之JpaSpecificationExecutor复杂动态查询实例
JpaSpecificationExecutor实现带查询条件的分页排序【详细】


Spring Data JPA入门简解与XML配置实现
SpringBoot + SpringData JPA + MySQL 的快速开始实例

你可能感兴趣的:(JavaEE,文章,SpringData)