我在数据库中只有一个名为 Student 的表。下面是我的代码中针对它的jpa实体:
@Entity
@Table(name = "student")
public class Student{
@Id
private Long id;
@Column
private String firstName;
@Column
@Embedded
@JsonUnwrapped
private School school;
}
public class School{
private Integer grade;//eg. 2nd, 3rd
private String type; //eg. primary, secondary
}
直到现在,代码仅用于获取所有学生及其数据或获取特定学生。因此,数据库模式就是这样。但是现在,我们有了一个新功能,其中我们需要根据特定的年级进行搜索并获取该特定年级的所有学生。或获取特定学校类型的所有学生,例如小学的所有学生。因此,需求完全颠倒了,因此我们需要将以下模式的返回值发送到前端:
class SchoolResponseDTO{
private String schoolType;
private List<Integer> grades;
}
class Grade{
private Integer id;
private List<Integer> studentId;
}
从现在开始,有点冗长,我们需要找到所有学校类型,然后是该学校类型的所有年级,然后是该学校类型和年级的所有学生。
直到现在,我们仍在使用Spring JpaRepository满足我们的要求。我认为这项新要求将需要自定义查询,并且我不认为可以使用JPARepository以直接的方式处理此问题。我只需要知道你的想法。无需自定义sql查询就可以做到吗?
答案 0 :(得分:0)
您可以使用Spring Data并使用类似此查询属性表达式的内容。来自文档:
属性表达式只能引用托管实体的直接属性,如前面的示例所示。在查询创建时,您已经确保已解析的属性是托管域类的属性。但是,您也可以通过遍历嵌套属性来定义约束。考虑以下方法签名:
List<Person> findByAddressZipCode(ZipCode zipCode);
假定一个人的地址带有邮政编码。在这种情况下,该方法将创建遍历属性x.address.zipCode。解析算法首先将整个部分(AddressZipCode)解释为属性,然后在域类中检查具有该名称的属性(未大写)。如果算法成功,它将使用该属性。如果不是,该算法将骆驼箱部分的源从右侧分为头和尾,并尝试找到对应的属性,在我们的示例中为AddressZip和Code。如果该算法找到了具有该头部的属性,则它将采用该头部,并继续从那里开始构建树,以刚才描述的方式将尾部向上拆分。如果第一个拆分不匹配,则算法会将拆分点移到左侧(地址,邮政编码)并继续。
尽管这在大多数情况下都可行,但是算法可能会选择错误的属性。假设Person类也具有addressZip属性。该算法将在第一个拆分回合中匹配,选择错误的属性,然后失败(因为addressZip的类型可能没有代码属性)。
要解决这种歧义,可以在方法名称中使用_手动定义遍历点。因此我们的方法名称如下:
List<Person> findByAddress_ZipCode(ZipCode zipCode);
由于我们将下划线字符视为保留字符,因此我们强烈建议您遵循以下标准Java命名约定(即,在属性名称中不使用下划线,而使用驼峰大小写)。
希望有帮助。