我正在用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对象。我怎么能实现这个功能呢?
答案 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属性。