首页 > 解决方案 > 休眠针对多对一关系执行的多个查询

问题描述

在处理一对多关系时,我们面临着一些奇怪的问题。为了详细描述,我们有以下实体,

RCAAssessmentUnit :-

@Entity
@Table(name = "RCAAssessmentUnit")
@Access(AccessType.FIELD)
public class RCAAssessmentUnit extends AbstractPersistentEntity implements Serializable {

    private static final long serialVersionUID = -3114793801627752533L;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "document", nullable = true)
    protected Document document;

    @Column(name = "Name", length = 150, nullable = false)
    protected String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "rca_assessment_unit_admin", nullable = true)
    @NotFound(action = NotFoundAction.IGNORE)
    protected RCAAssessmentUnitAdmin rcaAssessmentUnitAdmin;

RCAAssessmentUnitAdmin -

@Entity
@Table(name = "RCAAssessmentUnitAdmin")
@Access(AccessType.FIELD)
public class RCAAssessmentUnitAdmin extends AbstractPersistentEntity implements Serializable {

    private static final long serialVersionUID = 8890257035008399346L;

    // Name
    @Column(name = "Name", length = 150, nullable = false)
    protected String name;

    @Column(name = "changed$")
    protected Date changed;

    @OneToMany(mappedBy = "rcaAssessmentUnitAdmin", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    protected List<RCAAssessmentUnit> rcaAssessmentUnits;

BCDocument 扩展 Document 并维护继承连接策略。

@Entity
@PrimaryKeyJoinColumn(name = "Document")
@Table(name = "BCDocument")
@Access(AccessType.FIELD)
public class BCDocument extends Document 
------
   @OneToMany(mappedBy = "document", fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
    @OrderBy(value = "name")
    private List<RCAAssessmentUnit> rcaAssessmentUnits ;

文档 :-

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "Document", uniqueConstraints = { @UniqueConstraint(columnNames = { "Id" }) })
@Access(AccessType.FIELD)
public class Document extends AbstractPersistentEntity {

因此,有了这些关系,我们就有了一个管理模块来添加/删除/编辑“RCAAssessmentUnitAdmin”。主页首先列出了所有管理员,一旦我们尝试编辑从查询日志中添加到任何 BCDcouments 中的任何管理员,我们可以看到获取了多个查询以加载所有扩展“文档”实体的文档,例如AWT、CTT 等以及 BCDocument 例如

Hibernate: select rcaassessm0_.rca_assessment_unit_admin as ------ from RCAAssessmentUnit rcaassessm0_ where rcaassessm0_.rca_assessment_unit_admin in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select document0_.Id$ as Id1_48_0_, -----
from Document document0_ left outer join AWT document0_1_ on document0_.Id$=document0_1_.Document left outer join CTT document0_2_ on document0_.Id$=document0_2_.Document left outer join WCR document0_3_ on document0_.Id$=document0_3_.Document left outer join BRST document0_4_ on document0_.Id$=document0_4_.Document left outer join BCDocument document0_5_ on document0_.Id$=document0_5_.Document left outer join Impact_Analysis_RTO impactanal1_ on document0_.Impact_Analysis_Rto=impactanal1_.Id$ where document0_.Id$ in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

因此,第一个操作(列出所有管理员)确实保持所有关系“惰性”,但是一旦我们尝试编辑“管理员”,为什么它会尝试查询“文档”层次结构(如第二个查询所示)?在编辑它时,我们不需要文档关系或“admin”的子对象。此外,如果删除了“admin”,我们会将所有子项(RCAAssessmentUnit)的引用标记为 null,因为我们不想删除已添加到 BCDocument 中的子项。

我一直在阅读有关此问题的所有相关问答,还检查了 N+1 问题,但到目前为止无法在这里找出问题。任何建议将不胜感激。

更新: 下面是获取管理员列表的代码块。这两种方法都是支持 bean 的一部分,它是具有会话范围的接缝组件。

  public void retrieve() {
        TypedQuery<RCAAssessmentUnitAdmin> query = entityManager.createQuery("from RCAAssessmentUnitAdmin order by name", RCAAssessmentUnitAdmin.class);
        rcaAssessmentUnitItems = query.getResultList();
    }

我们有绑定此列表的 Richfaces 数据表,并且在编辑操作时,调用由下面处理。因此,即使在控件进入此编辑方法之前,在后端控制台中我也可以看到所有查询都在执行。

public void edit(RCAAssessmentUnitAdmin unitAdmin) {
    log.info("edit: " + unitAdmin);
RCAAssessmentUnitAdminScreen dialog = Util.getSeamComponent (RCAAssessmentUnitAdminScreen.class, true);
    dialog.setupDialog(unitAdmin, rcaAssessmentUnitItems);

}

    <rich:dataTable id="items" style="word-break: keep-all;" value="#{rcaAssessmentUnitItems}" var="row" rowKeyVar="rowKey" columnClasses="col" rowClasses="odd_row, even_row">
                        <f:facet name="footer">
                            <h:outputText value="No RCA Assessment Units Found" rendered="rcaAssessmentUnitItems == null or rcaAssessmentUnitItems.size == 0}"/>
                        </f:facet>
                        <rich:column style="text-align: center; width: 70px;">
                            <f:facet name="header"><h:outputText value="#" /></f:facet>
                        <div style="width:45px !important;margin: 0 auto !important;">
                            <a:commandButton execute="@this"  action="#{updateRCAAssessmentUnits.edit(row)}" styleClass="listItemBtn" value="#{rowKey + 1}"/>
                        </div>
                    </rich:column>
-----
</rich:dataTable>

标签: hibernatejpa

解决方案


推荐阅读