【问题标题】:Lazy loading collection of objects for insert with HQL延迟加载对象集合以使用 HQL 插入
【发布时间】:2014-11-20 16:22:59
【问题描述】:

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

考虑以下情况:我需要向所有学分 > 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 server的大量无用数据,上述查询非常慢并且占用大量内存。 我不能将所有属性直接延迟加载到实体中,因为这会杀死应用程序的其他区域。

我需要的是一种加载上述集合的方法,只获取 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,但我不知道该怎么做。

【问题讨论】:

    标签: java hibernate jpa hql hibernate-mapping


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      最后我只加载了 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,性能会好很多。

      【讨论】:

        猜你喜欢
        • 2020-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-21
        相关资源
        最近更新 更多