Pergunta

Se tiver uma entidade A com um mapeamento bidirecional um-ou-zero-para-um com entidade B.

O mapeamento é o seguinte:

<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 eu faço uma consulta HQL (ou melhor, uma consulta HQL nomeada) para EntityA, hibernate ansiosamente cargas EntityA # propertyB com uma instrução SELECT separado.

O meu problema é que, se os meus HQL retornos 1000 EntityA do (com todos os ter seu próprio respectivo EntityB), hibernate fará n + 1 consultas (1ª consulta seria para EntityA retornar 1000 resultados, enquanto os n perguntas seriam provenientes de o EntityA # propertyB selecionar carregamento lento).

No entanto, eu não preciso aqueles EntityA do # é por isso que eu quero carregar preguiçoso-los em vez (sem ter de hibernação usar uma consulta SQL separado) propertyB.

Isso é possível? E se é, como eu faço isso?

Obrigado, Franz

Foi útil?

Solução

Eu fixo este problema.

O que eu fiz foi criar transformar o campo EntityA # propertyB em um conjunto com o nome EntityA # propertyBs. Mas eu manteve o EntityA # getPropertyB () e EntityA # setPropertyB (EntityB propertyB) métodos de acesso.

Os corpos de método desses métodos de acesso são agora algo como isto:

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

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

Em seguida, no meu mapeamento, eu mapeado o conjunto EntityA # propertyBs e especificar o acesso ao 'campo'.

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

Com esta configuração, você pode agora criar um mapeamento preguiçoso do POJO possuir (EntityA) para o POJO propriedade (EntityB) mesmo se Table_A é propriedade de table_b.

Outras dicas

Resposta curta: Não, você não pode fazer isso, pelo menos não sem alterar o banco de dados eo mapeamento. Você basicamente tem que reverter o one-to-one mapeamento ea relação de chave estrangeira para o trabalho da maneira que você quiser.


resposta mais longa: Hibernate pode associações de carga preguiçosos. A forma como ele faz isso é através da injeção de um objeto proxy que contém o ID do objeto referenciado.

No seu caso, o mapeamento é tal que a coluna de chave estrangeira está em table_b, isto é, onde você usa o mapeamento muitos-para-um. Então, se você carregar um B, hibernate encontra a referência FK na coluna fk_a e pode criar um proxy que mantém este valor. Quando o proxy é acessado a entidade correspondente é carregado.

E se um registro da tabela A é selecionado? Hibenate irá criar um objeto A, mas para ser capaz de preencher o propertyB, ele vai ter que olhar para o table_b, para encontrar a linha correspondente com fk_a = a.id. Não há outro caminho para Hibernate para descobrir o que registro a carga em tempo de carregamento lento.

Na verdade, esta seria uma melhoria para o Hibernate, uma vez que também deve ser capaz de fazer o carregamento em outras chaves exclusivas, enquanto o carregamento lento, mas a implementação atual não permite isso, talvez você pode levantar um problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top