不加入子表的 JPA (@OneToMany) 查询

Posted

技术标签:

【中文标题】不加入子表的 JPA (@OneToMany) 查询【英文标题】:JPA (@OneToMany) query without joining child table 【发布时间】:2017-11-16 01:02:07 【问题描述】:

我正在使用 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 对象。我怎样才能实现这个功能?

【问题讨论】:

【参考方案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

【讨论】:

以上是关于不加入子表的 JPA (@OneToMany) 查询的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 Hibernate 的 JPA 注释来描述外键仅在子表中的 @OneToMany 关系

JPA 单向一对多关联关系

父表的主键是子表的主键,如何使用jpa进行映射?

spring Data jpa 一对多关联 动态查询怎么写

Jpa中ManyToMany和OneToMany的双向控制

Jpa中ManyToMany和OneToMany的双向控制