【发布时间】:2021-10-07 10:35:37
【问题描述】:
我有 3 个表:student、subject、student_subject_mapping。 学生和学科有多对多的关系,第三个表包含该特定学科的映射和标记。
Student:
| id | name | gpa |
|:---- |:------:| -----:|
| 1 | Tom | 7.0 |
| 2 | Jerry | 8.0 |
| 3 | Popeye | 7.5 |
Subject:
| id | name |
|:---- |:----------------:|
| 1 | Physics |
| 2 | Chemistry |
| 3 | Math |
| 4 | Computer Science |
student_subject_mapping:
| student_id | subject_id | score |
|:---------- |:----------:| -----:|
| 1 | 1 | 5.0 |
| 1 | 2 | 6.0 |
| 1 | 3 | 7.5 |
| 1 | 4 | 8.0 |
| 2 | 2 | 6.0 |
| 2 | 3 | 7.0 |
| 2 | 4 | 8.0 |
| 3 | 1 | 7.0 |
| 3 | 3 | 6.0 |
| 3 | 4 | 8.5 |
我想根据科目选择学生,比如物理、化学、数学、计算机科学,所以组合查询将类似于:
- 选择学生全部 4门科目分数 > 5和gpa > 6
- 选择至少 3门以上科目且分数 > 6和gpa > 7 的学生
- 选择至少“n”以上科目且分数 > 7和gpa > 7的学生
科目、“n”、分数和 gpa 是动态的
学生.java
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Student implements BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double gpa;
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<StudentSubjectMapping> studentSubjectMapping = new HashSet<>();
}
Subject.java
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Subject implements BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@JsonIgnore
@OneToMany(mappedBy = "subject")
private Set<StudentSubjectMapping> studentSubjectMapping = new HashSet<>();
}
@Entity
@Table
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class StudentSubjectMapping{
@EmbeddedId
StudentSubjectMappingId StudentSubjectMappingId;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("studentId")
private Student student;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("subjectId")
private Subject subject;
private Double score;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Embeddable
public class StudentSubjectMappingId implements Serializable {
private static final long serialVersionUID = 1L;
private Long studentId;
private Long subjectId;
}
我尝试了不同的东西(之前没有embeddedId)但没有任何帮助:
@Query("from Student student where student.subjects in :subjects group by student.subjects HAVING count(DISTINCT student.subjects) =:count ")
@Query("SELECT new com.nsia.model.Form(f.id, f.name, f.description, f.createdAt, g, COUNT(i.id)) from Form f " +
"LEFT JOIN f.instances JOIN f.groups g WHERE f.groups IN (?1) group by f.id")
@Query("from Student student LEFT JOIN student.subjects subjects WHERE subjects.id in :subjects group by student.subjects HAVING count(DISTINCT student.subjects.size) =:count ")
@Query("from Student student where student.id not in (SELECT stud.id from Student stud where stud.subjects not in (:subjects))")
@Query("select student from Student as student " +
"where student.id not in " +
"(select students.id from Student as students " +
"join students.subjects as subjects " +
"where subjects.id not in (:subjectIds))")
@Query(value = "select students.id from Student as students " +
"left join fetch students.subjects as subjects " +
"where subjects.id not in (:subjectIds) and students.id in (1,2,3)",
countQuery = "select count (student) from Student student left join student.subjects")
List<Long> getstudentIds(@Param("subjectIds") List<Long> subjectIds);
【问题讨论】:
-
如果可能,请将您的问题限制在一个查询范围内。
-
@TimBiegeleisen 现在好点了吗?我删除了 embeddedId 部分。
-
@TimBiegeleisen 顺便提一下,我只针对我提到的 3 个不同场景寻找一个查询。这些只是可能发生的情况的示例。
标签: spring spring-boot hibernate jpa spring-data-jpa