JPA(@OneToMany)查询没有加入子表

时间:2017-06-14 04:07:23

标签: java postgresql jpa spring-boot

我正在用JPA和Postgres db编写服务。我有一个名为Student的课程:

public class Student {
    @id
    private String id;

    private String firstName;
    private String lastName;

    @OneToMany(targetEntity = Phone.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "student_id", referencedColumnName = "id")
    private Set<Phone> phones;

    // Setter and Getter
}

还有一个电话课:

public class Phone {
    @id
    private String id;

    private String number;

    // Setter and Getter
}

现在我的数据库中将有两个表,其中包含以下列:

student:id,first_name,last_name

手机:ID,号码, student_id (由@JoinColumn生成)

现在,每当我查询学生时,JPA都会将电话表加入学生表,学生结果中包含该学生的电话信息。这正是我想要的。

但现在我遇到了一个问题。当我查询学生列表时,电话信息在这种情况下没用,只需要id,firstName和lastName。但JPA也为我做了同样的“加入”操作。我知道这会耗费大量时间。在这种情况下,我怎么能只返回学生表中的信息?没有加入手机桌?

我在存储库中试过像

这样的东西
@Query(SELECT s.id, s.firstName, s.lastName FROM student s)
public List<Student> findAllStudentWithoutPhone();

但它返回值列表,但未转换为Student对象。我怎么能实现这个功能呢?

3 个答案:

答案 0 :(得分:2)

fetch = FetchType.LAZY为您提供了在代码第一次调用之前不查询Phone表的可能性。请参阅:http://docs.oracle.com/javaee/7/api/javax/persistence/FetchType.html#LAZY

如果您想要检索没有电话的学生列表,查询应该是: @Query(SELECT * FROM student s where phones IS NULL)

要自动将结果转换为Student对象,请不要在查询中使用s.id, s.firstName, s.lastName

答案 1 :(得分:2)

在一对多映射(参见下文)中,您已将获取类型设置为延迟 fetch = FetchType.LAZY 因此,hibernate不会获取对应于学生,直到你通过getter方法访问这组手机,所以不用担心它。

@OneToMany(targetEntity = Phone.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "student_id", referencedColumnName = "id")
private Set<Phone>;

但是,如果您需要验证是否正常工作,可以将属性 show_sql 设置为true并检查通过hibernate生成的sql。

答案 2 :(得分:1)

@Sahil给出的答案是绝对正确的,但要补充一点。

@Cong 您不需要添加FetchType.LAZY,因为默认情况下它已经是LAZY。  &安培;作为注释,电话缺少变量名称的Student class属性。