Pregunta

Si tenga una entidad A con una bidireccional asignación uno o de cero a uno con la entidad B.

El mapeo es como sigue:

<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>

y

<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>

Cuando hago una consulta HQL (o más bien, una consulta HQL nombrada) para EntityA, hibernación ansiosamente carga EntityA # propertyB con una instrucción de selección por separado.

Mi problema con esto es que si mis declaraciones de HQL 1000 EntityA (con todo lo que tengan su propia respectiva EntityB de), Hibernate hacen n + 1 consultas (primera consulta sería para EntityA volviendo 1000 resultados, mientras que los n consultas estarían viniendo desde la EntityA # propertyB seleccione la carga diferida).

Sin embargo, no necesito los EntityA # propertyB de eso es por eso que quiero carga perezosa ellos en su lugar (sin tener hibernación utilizar una consulta SQL por separado).

¿Es posible? Y si lo es, ¿cómo puedo hacer eso?

Gracias, Franz

¿Fue útil?

Solución

He arreglado este problema.

Lo que hice fue crear gire el campo EntityA # propertyB en un conjunto con el nombre EntityA # propertyBs. Pero conservé la EntityA # getPropertyB () y EntityA # setPropertyB (EntityB propertyB) métodos de acceso.

Los cuerpos de los métodos de los métodos de acceso son ahora algo como esto:

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

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

A continuación, en mi asignación, que mapea los establecidos EntityA # propertyBs y especifique el acceso 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 esta configuración, ahora puede crear una asignación perezoso del POJO poseer (EntityA) a la propiedad POJO (EntityB) incluso si TABLE_A es propiedad de TABLE_B.

Otros consejos

Respuesta corta: No, no puedes hacer eso, al menos no sin cambiar la base de datos y el mapeo. Es, básicamente, tiene que invertir el uno-a-uno mapeo y la relación de clave externa para trabajar en la forma que desee.


Respuesta larga: Hibernate asociaciones de carga perezosos lata. La forma en que hace esto es mediante la inyección de un objeto proxy que contiene el ID del objeto referenciado.

En su caso, la asignación es tal que la columna de clave foránea está en TABLE_B, es decir, en el que utiliza el mapeo muchos-a-uno. Así que si se carga un B, de hibernación encuentra la referencia FK en la columna de la fk_a y puede crear un proxy que mantiene este valor. Cuando se accede el proxy se carga la entidad correspondiente.

¿Qué pasa si se selecciona un registro de la tabla A? Hibenate creará un objeto A, pero para ser capaz de llenar el propertyB, que tendrá que buscar en el TABLE_B, para encontrar la fila correspondiente con fk_a = a.id. No hay otro camino para Hibernate para averiguar qué registro para que inicie en el carga diferida.

En realidad, esto sería una mejora para Hibernate, ya que también debe ser capaz de hacer la carga sobre otras claves únicas mientras que la carga diferida, pero la implementación actual no lo permite, tal vez usted puede plantear un problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top