资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

Specification查询

Java 更新时间: 发布时间: 计算机考试归档 最新发布

Specification查询

Spring Data JPA 提供了-个Specifcation接口,Specification 接口封装了JPA的Criteria查询条件,从而可以通过此接口更加方便地使用Criteria查询。

接下来以示例的方式来详细讲解使用Specification的查询、分页、动态查询等操作。

项目目录

1.创建maven项目,

命名为springdatajpaspecificationtest

修改pom.xml文件

    4.0.0    com.example    springdatajpaspecificationtest    0.0.1-SNAPSHOT    springdatajpaspecificationtest    springdatajpaspecificationtest            spring-boot-starter-parent        org.springframework.boot        2.7.6                19        UTF-8        UTF-8        2.6.13                            org.springframework.boot            spring-boot-starter-thymeleaf                            org.springframework.boot            spring-boot-starter-web                            org.springframework.boot            spring-boot-starter-test            test                            org.springframework.boot            spring-boot-starter-data-jpa                            mysql            mysql-connector-java                            org.assertj            assertj-core                                                    org.springframework.boot                spring-boot-dependencies                ${spring-boot.version}                pom                import                                                                org.apache.maven.plugins                maven-compiler-plugin                3.8.1                                    19                    19                    UTF-8                                                        org.springframework.boot                spring-boot-maven-plugin                ${spring-boot.version}                                    com.example.springdatajpaspecificationtest.SpringdatajpaspecificationtestApplication                                        true                                                                            repackage                                                    repackage                                                                                    

2.配置基本属性。

修改application.properties文件(没有就按项目目录创建)

#########数据源信息配置#########数据库地址spring.datasource.url=jdbc:mysql://localhost:3306/springdatajpaspecification?characterEncoding=utf8&useSSL=false#用户名spring.datasource.username=root#密码spring.datasource.password=root#数据库驱动spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver#指定连接池中最大的活跃连接数spring.datasource.tomcat.max-active=20#指定连接池最大的空闲连接数spring.datasource.max-idle=8#指定必须保持连接到最小值spring.datasource.min-idle=8#指定启动连接池时,初始建立的连接数量spring.datasource.initial-size=10################################################# JPA持久化配置############################################### 持久化配置,指定数据库类型spring.jpa.database=MySQL#指定是否需要在日志中显示SQL语句spring.jpa.show-sql=true#指定自动创建|更新|验证数据库表结构等配置,配置成update#表示如果数据库中存在持久化类对应的表就不创建,不存在就创建对应的表spring.jpa.hibernate.ddl-auto=update#指定命名策略spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImplspring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl#指定数据库方言spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialectspring.jpa.open-in-view=true

3.创建持久化类

在src/main/java/com/example/springdatajpaspecificationtest下新建四个包,分别是bean、controller、repository、service。

在bean包中创建两个持久化类Student.java和Clazz.java

Student.java

package com.example.springdatajpaspecificationtest.bean;import javax.persistence.*;import java.io.Serializable;@Entity@Table(name="tb_student")//查询班级的学生信息//定义方法名称findStudentByClazzName到query中的查询语句的关系@NamedQuery(name="Student.findStudentByClazzName",query="select s from Student s where s.clazz.name = ?1")public class Student implements Serializable{    @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;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    public char getSex() {        return sex;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }    public Clazz getClazz() {        return clazz;    }    public void setClazz(Clazz clazz) {        this.clazz = clazz;    }    public void setName(String name) {        this.name = name;    }}

Clazz.java

package com.example.springdatajpaspecificationtest.bean;//因为class是java中的保留关键字,不能用于命名变量,所以使用读音相似的clazz来命名,这是约定俗成的。import javax.persistence.*;import java.io.Serializable;import java.util.HashSet;import java.util.Set;@Entity@Table(name = "tb_clazz")public class Clazz implements Serializable {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private int code;    private String name;    //班级与学生是一对多的关联    @OneToMany(            fetch = FetchType.LAZY,            targetEntity = Student.class,            mappedBy = "clazz"    )    private Set students=new HashSet<>();    public Clazz(){    }    public Clazz(String name){        this.name = name;    }    public int getCode() {        return code;    }    public void setCode(int code) {        this.code = code;    }    public void setName(String name) {        this.name = name;    }    public Set getStudents() {        return students;    }    public void setStudents(Set students) {        this.students = students;    }    public String getName() {        return name;    }}

4.定义数据访问层接口

在src/main/java/com/example/springdatajpaspecificationtest/repository下创建两个接口分别命名为StudentRepository.java和ClazzRepository.java

StudentRepository.java

package com.example.springdatajpaspecificationtest.repository;import com.example.springdatajpaspecificationtest.bean.Student;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;public interface StudentRepository extends JpaRepository , JpaSpecificationExecutor{}

ClazzRepository.java

package com.example.springdatajpaspecificationtest.repository;import com.example.springdatajpaspecificationtest.bean.Clazz;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;public interface ClazzRepository extends JpaRepository , JpaSpecificationExecutor{}

5.定义业务层类

在src/main/java/com/example/springdatajpaspecificationtest/service下创建SchoolService.java

package com.example.springdatajpaspecificationtest.service;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.annotation.Resource;import javax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.JoinType;import javax.persistence.criteria.Path;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import com.example.springdatajpaspecificationtest.bean.Clazz;import com.example.springdatajpaspecificationtest.bean.Student;import com.example.springdatajpaspecificationtest.repository.ClazzRepository;import com.example.springdatajpaspecificationtest.repository.StudentRepository;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Sort;import org.springframework.data.jpa.domain.Specification;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import org.springframework.util.StringUtils;@Servicepublic class SchoolService {    //注入数据访问层接口对象    @Resource    private StudentRepository studentRepository;    @Resource    private ClazzRepository clazzRepository;    @Transactional    public void saveClazzAll(List clazzs){        clazzRepository.saveAll(clazzs);    }    @Transactional    public void saveStudentAll(List students){        studentRepository.saveAll(students);    }        @SuppressWarnings("serial")//serial连续的    public List> getStusBySex(char sex){        List students=studentRepository.findAll(new Specification() {            @Override            public Predicate toPredicate(Rootroot,CriteriaQueryquery,            CriteriaBuilder cb){                //root.get("sex")表示获取sex这个字段名称,equal表示执行equal查询                //相当与select s from Student s where s.sex = ?1                Predicate p1= cb.equal(root.get("sex"), sex);                return p1;            }        });        List> results = new ArrayList<>();        //遍历查询出的学生对象,提取姓名、年龄、性别信息        for (Student student:students){            Map 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> getStusByDynamic(Student student){        List students = studentRepository.findAll(new Specification() {        @Override        public Predicate toPredicate(Rootroot, CriteriaQueryquery,                                     CriteriaBuilder cb){            //本集合用于封装查询条件            List predicates = new ArrayList();            if (student!=null){                                if (StringUtils.hasLength(student.getName())){                    //% 符号是通配符,表示匹配任意字符,包括空格和其他特殊字符。                    // 因此,将 % 添加到查询字符串的开头和结尾,以确保找到所有包含 student.getName() 子字符串的记录。                    predicates.add(cb.like(root. get("name"),"%" + student.getName() + "%"));                }                                if (StringUtils.hasLength(student.getAddress())){                    predicates.add(cb.like(root. get("address"),"%" + student.getAddress() + "%"));                }                                if (student.getSex() != '0'){                    predicates.add(cb.equal(root. get("sex"), student.getSex() ));                }                                if (student.getClazz() !=null && StringUtils.hasLength(student.getClazz().getName())){                    root.join("clazz", JoinType.INNER);                    Path 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> results = new ArrayList<>();        //遍历查询出的学生对象,提取姓名、年龄、性别信息        for(Student stu :students){            Map 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 getStusByPage(String clazzName , int pageIndex , int pageSize){        //指定排序参数对象:根据id,进行降序查询        Sort sort = Sort.by(Sort.Direction.DESC, "id");        //分页查询学生信息,返回分页实体对象数据        //page对象中包含了查询出来的数据信息以及与分页相关的信息        Pagepages = studentRepository.findAll(new Specification() {        @Override            public Predicate toPredicate(Rootroot,CriteriaQueryquery,                                         CriteriaBuilder cb){            root.join("clazz",JoinType.INNER);            Path cn = root.get("clazz").get("name");            Predicate p1 = cb.equal(cn, clazzName);            return p1;        }        },PageRequest.of(pageIndex-1, pageSize, sort));        return pages;    }}

6.定义分页的页面数据对象

在com/example/springdatajpaspecificationtest下新建一个包vo,vo下创建一个Java类PageData.java

package com.example.springdatajpaspecificationtest.vo;//此类用于封装分页查询出的数据信息import java.util.ArrayList;import java.util.List;import java.util.Map;public class PageData {    //定义一个变量用于存放当前页码    private int pageIndex;    //定义一个变量用于保存满足查询条件下用于分页的数据总量    private long totalCount;    //定义一个变量用于保存当前条件下可以分得总页数    private int pageSize;    //定义一个变量用于保存当前页码查询出的数据总量    private int pageNum;    //定义一个变量用于保存当前查询出来的学生信息    private List> stuDatas = new ArrayList<>();    public int getPageIndex() {        return pageIndex;    }    public void setPageIndex(int pageIndex) {        this.pageIndex = pageIndex;    }    public long getTotalCount() {        return totalCount;    }    public void setTotalCount(long totalCount) {        this.totalCount = totalCount;    }    public int getPageSize() {        return pageSize;    }    public void setPageSize(int pageSize) {        this.pageSize = pageSize;    }    public int getPageNum() {        return pageNum;    }    public void setPageNum(int pageNum) {        this.pageNum = pageNum;    }    public List> getStuDatas() {        return stuDatas;    }    public void setStuDatas(List> stuDatas) {        this.stuDatas = stuDatas;    }}

7.定义控制器类

在src/main/java/com/example/springdatajpaspecificationtest/controller下创建一个Java类,命名为StudentController.java

package com.example.springdatajpaspecificationtest.controller;import java.util.*;import javax.annotation.Resource;import com.example.springdatajpaspecificationtest.bean.Clazz;import com.example.springdatajpaspecificationtest.bean.Student;import com.example.springdatajpaspecificationtest.service.SchoolService;import com.example.springdatajpaspecificationtest.vo.PageData;import org.springframework.data.domain.Page;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/student")public class StudentController {    //注入SchoolService    @Resource    private SchoolService schoolService;    @RequestMapping("/save")    public String save() {        Clazz clazz1 = new Clazz("疯狂java开发1班");        Clazz clazz2 = new Clazz("疯狂java开发2班");        //保存班级对象数据        List clazzs = new ArrayList<>();        clazzs.add(clazz1);        clazzs.add(clazz2);        schoolService.saveClazzAll(clazzs);        Student swk = new Student("孙悟空","花果山",700,'男',clazz1);        Student zx = new Student("紫霞仙子","盘丝洞",500,'女',clazz1);        Student zzb = new Student("至尊宝","广州",500,'男',clazz1);        Student tsgz= new Student("铁扇公主","火焰山",500,'女',clazz2);        Student nmw = new Student("牛魔王","广州",500,'男',clazz2);        Student zzj = new Student("蜘蛛精","广州",700,'女',clazz2);        List students = new ArrayList<>();        students.add(swk);        students.add(zx);        students.add(zzb);        students.add(tsgz);        students.add(nmw);        students.add(zzj);        schoolService.saveStudentAll(students);        return "保存学生对象成功";    }    @RequestMapping("/getStusBySex")    public List> getStusBySex(char sex){        return schoolService.getStusBySex(sex);    }    //动态查询学生信息    //可以根据学生对象的姓名(模糊匹配)、地址查询(模糊匹配)、性别、班级查询学生信息    @RequestMapping("/getStusByDynamic")    List> getStusByDynamic(Student student){        return schoolService.getStusByDynamic(student);    }    //分页查询某个班级的学生信息    @RequestMapping("/getStusByPage")    PageData getStusByPage(String clazzName, int pageIndex, int pageSize){        //分页查询某个班级的学生信息        Page page=schoolService.getStusByPage(clazzName,pageIndex,pageSize);        List students=page.getContent();        List> stuDatas = new ArrayList<>();        for (Student stu :students){            Map stuMap = new HashMap<>();            stuMap.put("name", stu.getName());            stuMap.put("id", stu.getId());            stuMap.put("age", stu.getAge());            stuMap.put("sex", stu.getSex());            stuMap.put("address", stu.getAddress());            stuMap.put("clazzName", stu.getClazz().getName());            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.测试应用

启动MySQL数据库,创建一个 新的数据库,命名为springdatajpaspecification, 然后在org.fkit.springdatajpaspecificationtest包下新建App.java启动类,App.java 和之前的项目一致,此处不再赘述。右击该类运行main方法。Spring Boot项目启动后,JPA会在数据库中自动创建持久化类对应的tb_ student 和tb clazzz 表。

测试添加学生和班级信息,在浏览器中输入如下地址:

http://localhost:8080/student/save

请求会提交到StudentController类的save方法进行处理,执行完成返回“保存学生对象成功”,查看数据库中的数据。

测试性别查询学生信息,在浏览器中输入如下地址:

http://localhost:8080/student/getStusBySex?sex=女

测试动态查询学生信息,在浏览器中输入如下地址:

http://localhost:8080/student/getStusByDynamic?clazzName=疯狂java开发1班&sex=女

http://localhost:8080/student/getStusByDynamic?address=广州&sex=男

测试分页查询某个班级下的学生信息,在浏览器中输入如下地址:

http://localhost:8080/student/getStusByPage?clazzName=疯狂java开发1班&pageIndex=1&pageSize=2

查询第二页数据,在浏览器中输入如下地址:

http://localhost:8080/student/getStusByPage?clazzName=疯狂java开发1班&pageIndex=2&pageSize=2

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1094657.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【Specification查询】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2