Hibernate为多对一关系执行多个查询

时间:2018-04-26 07:45:26

标签: hibernate jpa

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

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中添加的子项。

我一直在阅读所有相关的q&amp; a,并检查了N + 1问题,但到目前为止还无法找出问题。任何建议都将受到高度赞赏。

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

  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>

0 个答案:

没有答案