【问题标题】:JPA/Hibernate querying but not assigning sub-objectJPA/Hibernate 查询但不分配子对象
【发布时间】:2011-12-19 15:08:08
【问题描述】:

好的,我认为我对 JPA/Hibernate 的理解有些缺失。我有两个表:代表学生的 STUDENTS 和代表学生对班级的作业的 CC。 CC 表有一个指向学生的 STUDENTID 列。我正在尝试做一个简单的查询,在其中返回 CC 记录及其关联的学生记录。我的 CC 类看起来像这样(删除了很​​多东西):

@Entity
@Table(name="cc")
public class CC {
    ...
    @Column(name="studentid", nullable=false, updatable=false)
    private Integer studentid;

    @ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
    @JoinColumns({ @JoinColumn(name="studentid", referencedColumnName="id",
        insertable=false, updatable=false) })
    private Student student;
    ...
}

我必须指定referencedColumnName,因为“ID”不是STUDENTS 表的主键。我想查询如下:

EntityManager em = getCurrentEntityManager();
Query query = em.createQuery ( "select cc from CC cc inner join fetch cc.student where cc.sectionid=:sectionid");
query.setParameter("sectionid", sectionId);
List<CC> rows = query.getResultList();
if (!CollectionUtils.isEmpty(rows)) for (CC cc: rows) {
    Student student = cc.getStudent();
    //// PROBLEM: student object is null here (though studentid is correct)!
}

我可以看到 hibernate 正在正确地执行查询,将表连接在一起,甚至在查询投影中返回学生表的列:

select cc0_.dcid as dcid21_0_, student1_.DCID as DCID7_1_, cc0_.course_number as course2_21_0_,
... student1_.FIRST_NAME as FIRST28_7_1_, student1_.GENDER as GENDER7_1_, ...
from cc cc0_ inner join STUDENTS student1_ 
on cc0_.studentid=student1_.ID where cc0_.sectionid=?

如上所述,问题在于 CC 的“学生”子对象始终为空,即使 STUDENTID 列不为空并且是正确的。我确定我做错了什么,但是什么?

【问题讨论】:

  • 迭代学生名单并获得他们的 CC 不是更好吗?
  • 如果我要查找给定学生所在的所有班级,那么可以。但我正在寻找相反的信息:我想要给定班级的所有抄送记录,同时我需要学生的信息。
  • 为什么需要studentid栏目private Student student;列已作为外键存储在 db 中,引用学生。
  • 这里我可能弄错了,但这是我的想法:这个类CC是一个现有的类。大多数调用者不会使用 CC 获取 Student 对象,但是其中许多调用者确实使用 CC 中已经存在的 studentId 列。我的想法是,如果我让 getStudentId() 改为返回 student.id,那些调用者的查询将被修改。我不认为我想要那个,因为这意味着回归风险。
  • 我怀疑你有一个名为 class 的表,它与学生有多对多的关系。在这种情况下,CC 将是一个连接表,并且不应该有一个类,除非该表提供的更多。然后,您可以在 Class 对象上调用 getStudents()。

标签: java hibernate jpa


【解决方案1】:

我可能对 hibernate 获取的方式有误,但是,这里的这一行可能会证明你的症结:

@ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})

由于您告诉 Hibernate 使用 LAZY 获取,它不会为引用的 Class 对象拉回持久的 Student 对象。这有助于查询加载时间,Hibernate 在开启延迟加载的情况下优化了对象子类继承。如果您将获取类型更改为EAGER,我想您会看到您所期望的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多