【问题标题】:JPA (@OneToMany) query without joining child table不加入子表的 JPA (@OneToMany) 查询
【发布时间】:2025-12-19 06:35:06
【问题描述】:

我正在使用 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
}

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

学生: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 对象。我怎样才能实现这个功能?

【问题讨论】:

    标签: java postgresql jpa spring-boot


    【解决方案1】:

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

    @聪 您不需要添加 FetchType.LAZY,因为默认情况下它已经 LAZY。 并注意电话缺少变量名称的 Student 类属性。

    【讨论】:

    • 谢谢@mAc,变量已添加。
    【解决方案2】:

    在一对多映射中(请参阅下文),您已将获取类型设置为惰性 fetch = FetchType.LAZY 因此休眠不会获取与学生对应的电话集,直到您通过 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。

    【讨论】:

      【解决方案3】:

      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)

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

      【讨论】: