精通 Spring Boot 系列 11

简介: 精通 Spring Boot 系列 11

阅读全文,约 18 分钟

这是江帅帅的第013篇原创

案例4:Specification 查询
1)编辑 pom.xml 文件(与 CrudRepository 接口案例一样)
2)编辑 application.properties 文件(与 CrudRepository 接口案例一样)
3)创建 Clazz 和 Student 持久化类

先来看 Clazz 类。

@Entity
@Table(name="tb_clazz")
public class Clazz implements Serializable{
 
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int code ;
    private String name ;
 
    // 班级与学生是一对多的关联
    @OneToMany(
               fetch=FetchType.LAZY,
               targetEntity=Student.class,
               mappedBy="clazz"
            )     
    private Set<Student> students = new HashSet<>();
 
    public Clazz() {
 
    }
    // 班级对象
    public Clazz(String name) {
        this.name = name;
    }
    // setXxx 和 getXxx 方法
}

再来看看 Student 类。

@Entity
@Table(name="tb_student")
public class Student implements Serializable{
 
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name ;
    private String address ;
    private int age ; 
    private char sex;
 
    // 学生与班级是多对一的关系,这里配置的是双向关联
    @ManyToOne(fetch=FetchType.LAZY,
            targetEntity=Clazz.class
            )
    @JoinColumn(name="clazzId",referencedColumnName="code")
    private Clazz clazz ;
    public Student() {
 
    }
 
    public Student(String name, String address, int age, char sex,
            Clazz clazz) {
        super();
        this.name = name;
        this.address = address;
        this.age = age;
        this.sex = sex;
        this.clazz = clazz;
    }
    // setXxx 和 getXxx 方法
}
4)创建 ClazzRepository 和 StudentRepository 数据访问接口

先看 ClazzRepository 类。

public interface ClazzRepository extends JpaRepository<Clazz, Integer> ,JpaSpecificationExecutor<Clazz>{
}

再看 StudentRepository 类。

public interface StudentRepository extends JpaRepository<Student,Integer>,JpaSpecificationExecutor<Student>{
}
5)创建 ShcoolService 业务层
@Service
public class ShcoolService {
    // 注入数据访问层接口对象 
    @Resource
    private StudentRepository studentRepository;
    @Resource
    private ClazzRepository clazzRepository;
    @Transactional
    public void saveClazzAll(List<Clazz> clazzs) {
        clazzRepository.saveAll(clazzs);
    }
    @Transactional
    public void saveStudentAll(List<Student> students) {
        studentRepository.saveAll(students);
    }
 
    /**
     * 根据性别查询学生信息
     */
    @SuppressWarnings("serial")
    public List<Map<String, Object>> getStusBySex(char sex) {
        List<Student> students = studentRepository.findAll(new Specification<Student>() {
 
            @Override
            public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query,
                    CriteriaBuilder cb) {
               Predicate p1 = cb.equal(root.get("sex"), sex);
               return p1;
            }
        });
        List<Map<String, Object>>  results = new ArrayList<>(); 
 
        for(Student student:students){
            Map<String , Object> stu = new HashMap<>(); 
            stu.put("name", student.getName());
            stu.put("age", student.getAge());
            stu.put("sex", student.getSex());
            results.add(stu);
        }
        return results;
    }
 
 
    /**
     * 动态查询学生信息 
     * 可以根据学生对象的姓名(模糊匹配)
     * 地址查询(模糊匹配)、性别、班级查询学生信息 
     * 如果没有传输参数,默认查询所有的学生信息
     */
    @SuppressWarnings("serial")
    public List<Map<String, Object>> getStusByDynamic(Student student) {
        List<Student> students = studentRepository.findAll(new Specification<Student>() {
            @Override
            public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query,
                    CriteriaBuilder cb) {
                // 本集合用于封装查询条件
                List<Predicate> predicates = new ArrayList<Predicate>();  
                if(student!=null){
                    /** 是否传入了姓名来查询  */
                    if(!StringUtils.isEmpty(student.getName())){
                        predicates.add(cb.like(root.<String> get("name"),"%" + student.getName() + "%"));
                    }
                    /** 是否传入了地址来查询  */
                    if(!StringUtils.isEmpty(student.getAddress())){
                        predicates.add(cb.like(root.<String> get("address"),"%" + student.getAddress() + "%"));
                    }
                    /** 是否传入了性别来查询 */
                    if(student.getSex() != '\0'){
                        predicates.add(cb.equal(root.<String> get("sex"),student.getSex()));
                    }
                    /** 判断是否传入了班级信息来查询 */
                    if(student.getClazz()!=null && !StringUtils.isEmpty(student.getClazz().getName())){
                        root.join("clazz", JoinType.INNER);
                        Path<String> clazzName = root.get("clazz").get("name");
                        predicates.add(cb.equal(clazzName, student.getClazz().getName()));
                    }
                }
                return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        });
 
        List<Map<String, Object>>  results = new ArrayList<>(); 
 
        for(Student stu :students){
            Map<String , Object> stuMap = new HashMap<>(); 
            stuMap.put("name", stu.getName());
            stuMap.put("age", stu.getAge());
            stuMap.put("sex", stu.getSex());
            stuMap.put("address", stu.getAddress());
            stuMap.put("clazzName", stu.getClazz().getName());
            results.add(stuMap);
        }
        return results;
    }
    /**
     * 分页查询某个班级的学生信息
     */
    @SuppressWarnings("serial")
    public Page<Student> getStusByPage(String clazzName , int pageIndex , int pageSize ) {
        // 指定排序参数对象:根据id,进行降序查询
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        // 分页查询学生信息,返回分页实体对象数据
        // pages对象中包含了查询出来的数据信息,以及与分页相关的信息
        Page<Student> pages = studentRepository.findAll(new Specification<Student>() {
            @Override
            public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query,
                    CriteriaBuilder cb) {
                root.join("clazz", JoinType.INNER);
                Path<String> cn = root.get("clazz").get("name");
                Predicate p1 = cb.equal(cn, clazzName);
                return p1 ;
            }
        },PageRequest.of(pageIndex-1, pageSize, sort));
        return pages;
    }
}
6)创建分页对象

添加 nx.vo 文件夹,然后创建分页对象,具体如下:

public class PageData {
    // 定义一个变量用于存放当前页码 
    private int pageIndex;
    // 定义一个变量用于保存满足查询条件下用于分页的数据总量
    private long totalCount  ;
    // 定义一个变量用于保存当前条件下总共可以分的总页数
    private int pageSize ;
    // 定义一个变量用于保存当前页码查询出的数据总量
    private int pageNum;
    // 定义一个变量用于保存当前查询出来的学生信息 
    private List<Map<String,Object>> stuDatas = new ArrayList<>();
 
    // setXxx 和 getXxx 方法     
}
7)创建 StudentController 控制器类
@RestController
@RequestMapping("/student")
public class StudentController {
 
    // 注入ShcoolService
    @Resource
    private ShcoolService shcoolService;
    @RequestMapping("/save")
    public String save() {
 
        Clazz clazz1 = new Clazz("架构师001班");
        Clazz clazz2 = new Clazz("架构师002班");
        // 保存班级对象数据
        List<Clazz> clazzs = new ArrayList<>();
        clazzs.add(clazz1);
        clazzs.add(clazz2);
        shcoolService.saveClazzAll(clazzs);
 
        Student s1 = new Student("小黄","广州",17,'男',clazz1);
        Student s2 = new Student("小红","成都",15,'女',clazz1);
        Student s3 = new Student("小绿","上海",15,'男',clazz1);
        Student s4 = new Student("小豆","北京",15,'女',clazz2);
        Student s5 = new Student("小牛","西藏",15,'男',clazz2);
        Student s6 = new Student("小兰","黑龙江",17,'女',clazz2);
 
        List<Student> students = new ArrayList<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        students.add(s5);
        students.add(s6);
        shcoolService.saveStudentAll(students);
        return "保存学生成功";
    }
 
    @RequestMapping("/getStusBySex")
    public List<Map<String, Object>> getStusBySex(char sex){
        return shcoolService.getStusBySex(sex);
    } 
 
    // 动态的查询学生信息 
    @RequestMapping("/getStusByDynamic")
    public List<Map<String, Object>> getStusByDynamic(Student student) {
        return shcoolService.getStusByDynamic(student);
    }
 
    // 分页查询某个班级下的学生信息
    @RequestMapping("/getStusByPage")
    public PageData getStusByPage(String clazzName , int pageIndex , int pageSize ) {
        // 分页查询某个班级的学生信息
        Page<Student> page = shcoolService.getStusByPage(clazzName , pageIndex , pageSize);
        // 对查询出来的结果数据进行分析
        List<Student> students = page.getContent();
        List<Map<String,Object>> stuDatas = new ArrayList<>();
        for(Student stu :students){
            Map<String , Object> stuMap = new HashMap<>(); 
            stuMap.put("id", stu.getId());
            stuMap.put("name", stu.getName());
            stuMap.put("age", stu.getAge());
            stuMap.put("sex", stu.getSex());
            stuMap.put("address", stu.getAddress());
            stuMap.put("clazzName", clazzName);
            stuDatas.add(stuMap);
        }
 
        // 将分页查询出的结果数据进行分析,然后把数据存入到PageData对象中去保存起来响应给浏览器展示 
        PageData data = new PageData();
        data.setStuDatas(stuDatas);
        data.setPageIndex(page.getNumber()+1);
        data.setPageSize(page.getTotalPages());
        data.setTotalCount(page.getTotalElements());
        data.setPageNum(page.getSize());
        return data ;
    } 
}
8)测试

http://localhost:8080/student/save

目录
相关文章
|
12天前
|
Java 数据库连接 数据库
精通 Spring Boot 系列 13
精通 Spring Boot 系列 13
23 0
|
12天前
|
安全 Java 应用服务中间件
精通 Spring Boot 系列 03
精通 Spring Boot 系列 03
23 0
|
12天前
|
JSON Java fastjson
精通 Spring Boot 系列 05
精通 Spring Boot 系列 05
18 0
|
12天前
|
Java 关系型数据库 数据库连接
精通 Spring Boot 系列 07
精通 Spring Boot 系列 07
18 0
|
8月前
|
存储 缓存 算法
Spring Boot 中的 ConcurrentMapCacheManager
Spring Boot 中的 ConcurrentMapCacheManager
|
11月前
|
存储 JSON 安全
Spring Boot 安全
1.概述 在后端来说,安全主要就是控制用户访问,让对应权限的用户能访问到对应的资源,主要是两点: 认证 授权 认证,确定是谁。 授权,核实权限。 每个安全框架其实都是为了实现这两点。 目前常用的实现方式有如下几种: token JWT oauth spring security 前三种是理念,最后一种是开箱即食的框架。 2.token 2.1.理论 token ,也叫“令牌”,是验证用户身份的凭证。token的组成具有随意性,能标识用户身份即可。
99 0
|
XML 监控 Java
初学Spring Boot 必须要知道的事
Spring Boot简介 Spring Boot 核心功能 Spring Boot的优缺点 SpringBoot 常用注解和原理
138 0
|
XML 前端开发 IDE
5 分钟快速理解 Spring Boot
前言 Spring 是 Java 开发人员接触最多的框架,包括我在内的很多小伙伴只是对 Spring 进行简单使用,为了深入了解 Spring,我在 2020 年 6 月底的时候开始了 Spring 探索之路,并开设了《重学 Spring》专栏,到目前为止已经更新了 51 篇,内容涵盖了 Spring IOC、Spring AOP、Spring MVC 等内容,详细的介绍了 Spring 的核心特性与底层原理,也希望在读的小伙伴能更上一层楼。
76 0
5 分钟快速理解 Spring Boot
|
XML NoSQL Java
欢迎光临Spring Boot时代(一)2
欢迎光临Spring Boot时代(一)2
欢迎光临Spring Boot时代(一)2
|
XML Java 应用服务中间件
欢迎光临Spring Boot时代(一)1
欢迎光临Spring Boot时代(一)1
欢迎光临Spring Boot时代(一)1