我需要通过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,但我不知道该怎么做。
答案 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并且性能要好得多。