其他分享
首页 > 其他分享> > Specification的基本使用

Specification的基本使用

作者:互联网

Specification的基本使用

Specification是啥,相信你都需要使用了,我就不过多介绍了,直接上代码

1.基础表结构

create database jpa;
use jpa;

CREATE TABLE `teacher` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(16) NOT NULL,
  `age` int(4) NOT NULL,
  `teacher_no` int(8) NOT NULL,
  `status` char(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO jpa.teacher (name,age,teacher_no,status) VALUES
	 ('joshuay',20,1001,'Y'),
	 ('felixf',30,1002,'Y'),
	 ('stanh',25,1003,'Y');
	 
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `teacher_no` int(8) NOT NULL,
  `name` varchar(16) NOT NULL,
  `status` char(1) NOT NULL,
  `age` int(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO jpa.student (teacher_no,name,status,age) VALUES
	 (1001,'张三','Y',15),
	 (1001,'李四','Y',20),
	 (1002,'王五','Y',25),
	 (1002,'赵六','Y',30),
	 (1003,'金七','Y',35);

2.建立实体类

Teacher类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(catalog = "jpa", name = "teacher")
public class Teacher implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

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

    @Column(name = "age")
    private Integer age;

    @Column(name = "teacher_no")
    private Integer teacherNo;

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

    // @JsonIgnore
    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
    @JoinColumn(name = "teacher_no", referencedColumnName = "teacher_no", insertable = false, updatable = false)
    private List<Student> studentList;

}

Student类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(catalog = "jpa", name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

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

    @Column(name = "age")
    private Integer age;

    @Column(name = "teacher_no")
    private Integer teacherNo;

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

}

3.建立对应的Repository接口并继承相应的接口

public interface TeacherRepository extends JpaRepository<Teacher, Integer>, JpaSpecificationExecutor<Teacher> {
}

4.编写相应的Specification代码并进行单元测试

编写Specification实现逻辑

public class TeacherRepositorySpec {

    private TeacherRepositorySpec() {
    }

    public static Specification<Teacher> byTeacherName(@NonNull String name) {
        return (root, query, builder) -> {
            Predicate conjunction = builder.conjunction();
            List<Expression<Boolean>> expressions = conjunction.getExpressions();
            expressions.add(builder.equal(root.get("name"), name));
            return conjunction;
        };
    }

    public static Specification<Teacher> byReportForm(Map<String, Object> reportForm) {
        return (root, query, builder) -> {
            List<Predicate> sqlList = new ArrayList<>();
            sqlList.add(builder.equal(root.get("status"), "Y"));

            if (!ObjectUtils.isEmpty(reportForm.get("name"))) {
                String name = (String) reportForm.get("name");
                sqlList.add(builder.like(root.get("name"), "%" + name + "%"));
            }
            // join table student
            Join<Teacher, Student> studentJoin = root.join("studentList");
            studentJoin = studentJoin.on(builder.equal(studentJoin.get("status"), "Y"));
            if (!ObjectUtils.isEmpty(reportForm.get("age"))) {
                Integer age = (Integer) reportForm.get("age");
                sqlList.add(builder.gt(studentJoin.get("age"), age));
            }
            query.where(sqlList.toArray(new Predicate[0]));
            return null;
        };
    }


    public static Specification<Teacher> byAgeRange(Integer min,Integer max) {
        return (root, query, builder) -> {
            Assert.isTrue(Integer.compare(max,min) == 1,"max can not more than min");
            List<Predicate> sqlList = new ArrayList<>();
            sqlList.add(builder.equal(root.get("status"), "Y"));
            // join table student
            Join<Teacher, Student> studentJoin = root.join("studentList");
            studentJoin = studentJoin.on(builder.equal(studentJoin.get("status"), "Y"));
            sqlList.add(builder.between(root.get("age"),min,max));
            return builder.and(sqlList.toArray(new Predicate[0]));
        };
    }

}

单元测试

@SpringBootTest
class DemoSpringApplicationTests {

    @Autowired
    private TeacherRepository teacherRepository;

    @Test
    void test_spec() {

        Specification<Teacher> spec1 = TeacherRepositorySpec.byAgeRange(19, 26);
        List<Teacher> rangeTeacherList = teacherRepository.findAll(spec1);
        rangeTeacherList.forEach(System.out::println);
        System.out.println("================================================");
        Specification<Teacher> spec2 = TeacherRepositorySpec.byTeacherName("felixf");
        List<Teacher> nameTeacherList = teacherRepository.findAll(spec2);
        nameTeacherList.forEach(System.out::println);
        System.out.println("================================================");
        HashMap<String,Object> reportForm = new HashMap<String,Object>(){
            {
                put("name","h");
                put("age",20);
            }
        };
        Specification<Teacher> spec3 = TeacherRepositorySpec.byReportForm(reportForm);
        List<Teacher> formTeacherList = teacherRepository.findAll(spec3);
        formTeacherList.forEach(System.out::println);

    
    /* 打印日志以及输出结果如下:
    select
        teacher0_.id as id1_8_,
        teacher0_.age as age2_8_,
        teacher0_.name as name3_8_,
        teacher0_.status as status4_8_,
        teacher0_.teacher_no as teacher_5_8_ 
    from
        jpa.teacher teacher0_ 
    inner join
        jpa.student studentlis1_ 
            on teacher0_.teacher_no=studentlis1_.teacher_no 
            and (
                studentlis1_.status=?
            ) 
    where
        teacher0_.status=? 
        and (
            teacher0_.age between 19 and 26
        )
        
    Teacher(id=1, name=joshuay, age=20, teacherNo=1001, status=Y, studentList=[Student(id=1, name=张三, age=15, teacherNo=1001, status=Y), Student(id=2, name=李四, age=20, teacherNo=1001, status=Y)])
    Teacher(id=1, name=joshuay, age=20, teacherNo=1001, status=Y, studentList=[Student(id=1, name=张三, age=15, teacherNo=1001, status=Y), Student(id=2, name=李四, age=20, teacherNo=1001, status=Y)])
    Teacher(id=3, name=stanh, age=25, teacherNo=1003, status=Y, studentList=[Student(id=5, name=金七, age=35, teacherNo=1003, status=Y)])
================================================
    select
        teacher0_.id as id1_8_,
        teacher0_.age as age2_8_,
        teacher0_.name as name3_8_,
        teacher0_.status as status4_8_,
        teacher0_.teacher_no as teacher_5_8_ 
    from
        jpa.teacher teacher0_ 
    where
        teacher0_.name=?
        
    Teacher(id=2, name=felixf, age=30, teacherNo=1002, status=Y, studentList=[Student(id=3, name=王五, age=25, teacherNo=1002, status=Y), Student(id=4, name=赵六, age=30, teacherNo=1002, status=Y)])
================================================
    select
        teacher0_.id as id1_8_,
        teacher0_.age as age2_8_,
        teacher0_.name as name3_8_,
        teacher0_.status as status4_8_,
        teacher0_.teacher_no as teacher_5_8_ 
    from
        jpa.teacher teacher0_ 
    inner join
        jpa.student studentlis1_ 
            on teacher0_.teacher_no=studentlis1_.teacher_no 
            and (
                studentlis1_.status=?
            ) 
    where
        teacher0_.status=? 
        and (
            teacher0_.name like ?
        ) 
        and studentlis1_.age>20

    Teacher(id=3, name=stanh, age=25, teacherNo=1003, status=Y, studentList=[Student(id=5, name=金七, age=35, teacherNo=1003, status=Y)])
     */
    }
}

标签:基本,status,name,age,teacher,_.,teacher0,使用,Specification
来源: https://www.cnblogs.com/jiehao-yu/p/16460004.html