使用HQL延迟加载对象的集合

时间:2014-09-25 19:12:39

标签: java hibernate jpa hql hibernate-mapping

我需要通过HQL从DB加载一组对象,目的是仅使用这些对象在一些新记录中设置关联。

请考虑以下事项:我需要向所有具有nr个学分的学生发送电子邮件> 50,我需要跟踪传输中包含的所有收件人。

首先选择学生:

Query query = sessionFactory.getCurrentSession().createQuery("from Student student left join fetch student.scores where student.credits>50");
List<Student> students = query.list();

这将返回一个学生列表,其中包含为每条记录加载的所有列(非关联属性,如名字,姓氏,出生日期......)。 问题是当我有大量数据时,由于从db传输到app服务器的大量无用数据,上述查询非常慢并且占用大量内存。 我不能直接在实体中加载延迟所有属性,因为这会杀死应用程序的其他区域。

我需要的是一种加载上述集合的方法,只使用获取的ID,因为我正在使用对象来为关联中的一些新对象设置它们。我知道这可以很容易地为OneToMany协会完成,但我怎么能直接查询收集呢?

List<Recipient> emailRecipients = new ArrayList<>();
for(Student student: students){
   Recipient rec = new Recipient();

   //this is the only usage of the student object
   rec.setStudent(student);
   ...
   set other properties for the recipient
   sessionFactory.getCurrentSession().save(rec);
}

在收件人内部,Student对象的设置如下:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "STD_ID", nullable = false)
private Student student;

如您所见,只需要Student对象的id,但我不知道该怎么做。

2 个答案:

答案 0 :(得分:1)

您可以使用一种特定于Hibernate的技巧,即使您没有提供实际的管理实体,也可以设置FK关联。我们假设我们有一个studentId,我们可以简单地设置:

Student student = new Student();
student.setId(studentId);
rec.setStudent(student);

标准JPA不支持此功能,但它适用于Hibernate。只要确保你没有从孩子到父母的任何级联传播(你不应该有这种传播)。

答案 1 :(得分:0)

最后我只加载了studentId并修改了收件人内部的映射以包含studentId:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "STD_ID", insertable=false, updatable = false)
private Student student;

@Column(name = "STD_ID", nullable = false)
private Long studentId;

现在我可以简单地设置studentId并且性能要好得多。