Spring data jpa Specification 子查询实现

Spring data jpa Specification 子查询实现

      • 使用到的类
      • 前期准备工作
      • 子查询例子

在使用Spring data jpa进行没有实体关联的相关查询时无法使用 get("fieldName)或者join的方法进行操作时,可采用子查询来对另一个实体进行查询,并将查询结果作为原来查询(父查询)的查询条件值。

使用到的类

javax.persistence.criteria.Subquery<T> // 子查询类
javax.persistence.criteria Root<X> 
javax.persistence.criteria.Join<Z, X> // 在子查询中有使用到连接查询 z:当前查询类,x:连接类

前期准备工作

创建实体类Student和Teacher(使用到了lombok包的@Data注解),如下:

import lombok.Data;
import javax.persistence.*;
import java.util.List;

/**
 * 学生类
 */
@Entity
@Table(name = "student")
@Data
public class Student {
    @Id
    @SequenceGenerator(name = "increment")
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "increment")
    private Integer id;

    @Column(name = "name", columnDefinition = "varchar(128) comment '姓名'")
    private String name;

    @ManyToMany
    @JoinTable(name = "teacher_student",
            joinColumns = {@JoinColumn(name = "student_id")},
            inverseJoinColumns = {@JoinColumn(name = "teacher_id")}
    )
    private List<Teacher> teachers;
}
import lombok.Data;
import javax.persistence.*;
/**
 * 教师类
 */
@Entity
@Table
@Data
public class Teacher {

    @Id
    @GeneratedValue(generator = "increment", strategy = GenerationType.AUTO)
    @SequenceGenerator(name="increment")
    private Integer id;

    @Column(name = "name", columnDefinition = "varchar(128) comment '姓名'")
    private String name;
}

以及对应repository的创建,继承 org.springframework.data.jpa.repository.JpaRepositoryorg.springframework.data.jpa.repository.JpaSpecificationExecutor两个接口

子查询例子

以Teacher为查询对象,查询姓名为张三的所有老师的信息。

/**
 * 根据学生名字查询对应老师信息
 * @param name 学生姓名
 */
public String findTeacherByStudentName(String name) {
    List<Teacher> list = teacherRepository.findAll(new Specification<Teacher>() {
        @Override
        public Predicate toPredicate(Root<Teacher> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            Predicate predicate = cb.conjunction();
            // 创建子查询,并指定子查询实体对象
            Subquery<Student> subQuery = query.subquery(Student.class);
            Root<Student> subRoot = subQuery.from(Student.class);
            // 通过连接查询到学生对应的教师id
            Join<Student, Teacher> join = subRoot.join("teachers", JoinType.LEFT);
            // 设置子查询的查询字段,
            // 相当于 select teacher.id
            // 若要查询全部,即select * ,则直接设置 subQuer.select(subRoot);即可
            subQuery.select(join.get("id"));
            // 创建查询条件,学生姓名=name
            Predicate subPredicate = cb.equal(subRoot.get("name"), name);
            // 子查询条件
            subQuery.where(subPredicate);
            // 将子查询结果作用查询的条件,添加到父查询中
            Expression<String> exp = root.get("id");
            Predicate p1 = exp.in(subQuery);
            predicate.getExpressions().add(p1);
            return predicate;
        }
    });
    StringBuilder teacherInfo = new StringBuilder("");
    list.forEach(a -> {System.out.println(a.toString()); teacherInfo.append(a.toString()).append("\r\n");});
    return teacherInfo.toString();
}

你可能感兴趣的:(spring)