Domanda

Se abbia un'entità A con un bidirezionale mappatura uno o zero-a-uno con l'entità B.

La mappatura è la seguente:

<class name="EntityA" table="TABLE_A" mutable="true" lazy="true">
    <id name="idA" type="long" column="pk_a" unsaved-value="null">
        <generator class="sequence">
            <param name="sequence">pk_a_seq</param>
        </generator>
    </id>
    <one-to-one name="propertyB" class="EntityB" property-ref="propertyA" constrained="true" outer-join="false"/>
</class>

e

<class name="EntityB" table="TABLE_B" mutable="true" lazy="true">
    <id name="idB" type="long" column="pk_b" unsaved-value="null">
        <generator class="sequence">
            <param name="sequence">pk_b_seq</param>
        </generator>
    </id>
    <many-to-one name="propertyA" class="EntityA" not-null="true" unique="true" lazy="proxy" column="fk_a"/>
</class>

Quando faccio una query HQL (o meglio, una query HQL di nome) per EntityA, hibernate avidamente carica EntityA # propertyB con un'istruzione select separata.

Il mio problema è che se le mie dichiarazioni HQL 1000 EntityA (con tutti con il loro rispettivo EntityB di), ibernazione farà n + 1 query (prima interrogazione sarebbe per EntityA restituire 1000 risultati, mentre le n query sarebbe venuta da l'EntityA # propertyB selezionare lazy loading).

Tuttavia, non ho bisogno di quelle EntityA # propertyB di è per questo che voglio loro, invece di carico pigri (senza avere Hibernate utilizzare una query SQL separato).

È possibile? E se lo è, come faccio a fare questo?

Grazie, Franz

È stato utile?

Soluzione

Ho risolto questo problema.

Quello che ho fatto è stato quello di creare ruotare il campo EntityA # propertyB in un set con il nome EntityA # propertyBs. Ma ho mantenuto l'EntityA # getPropertyB () e EntityA # setPropertyB (EntityB propertyB) metodi di accesso.

I corpi dei metodi di questi metodi di accesso sono ora qualcosa di simile:

public EntityB getPropertyB() {
    return CollectionUtils.get(propertyBs, 0);
}

public void setPropertyBs(EntityB propertyB) {
    propertyBs= Collections.singleton(propertyB);
}

Poi nel mio mappatura, ho mappato il set EntityA # propertyBs e specificare l'accesso al 'campo'.

<set name="scheduledAdInfos" lazy="true" fetch="subselect" access="field" cascade="none" inverse="true">
    <key column="pk_a"/>
    <one-to-many class="EntityB"/>
</set>

Con questa impostazione, è ora possibile creare una mappatura pigro dal POJO possedere (EntityA) al POJO di proprietà (EntityB) anche se TABLE_A è di proprietà di TABLE_B.

Altri suggerimenti

Risposta breve: No, non si può fare, almeno non senza cambiare il database e la mappatura. Che, fondamentalmente, deve invertire l'one-to-one mappatura e la relazione chiave esterna per lavorare nel modo desiderato.


Più rispondere: Hibernate può associazioni di carico pigri. Il modo in cui fa questo è iniettando un oggetto proxy che contiene l'ID dell'oggetto di riferimento.

Nel vostro caso, la mappatura è tale che la colonna chiave esterna è in TABLE_B, cioè, in cui si utilizza la mappatura molti-a-uno. Quindi, se si carica un B, Hibernate trova il riferimento FK nella colonna fk_a e può creare un proxy che contiene questo valore. Quando il proxy si accede viene caricato l'entità corrispondente.

Che cosa succede se si seleziona un record dalla tabella A? Hibenate creerà un Un oggetto, ma per essere in grado di riempire il propertyB, dovrà esaminare la TABLE_B, trovare la riga corrispondente con fk_a = a.id. Non c'è altro modo per Hibernate per scoprire che cosa disco che si carica al lazy loading.

In realtà, questo sarebbe un miglioramento per Hibernate, dal momento che dovrebbe anche essere in grado di fare il carico su altre chiavi univoche, mentre caricamento pigro, ma l'implementazione attuale non consente questo, forse si può sollevare una questione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top