Tipo de busca padrão para um-para-um, muitos-para-um e um-para-muitos no Hibernate


103

Qual é o tipo de busca padrão em mapeamentos de hibernação?

O que aprendi depois de explorar é:

  • para um a um, é ansioso .
  • para um-para-muitos é preguiçoso .

Mas depois de testá-lo no Eclipse, ele estava ansioso por todos.

Depende se estou usando JPA ou Hibernate?


1
Caso você ainda esteja envolvido em tópicos de JPA - atualizei sua pergunta com uma nova resposta, já que as antigas estão desatualizadas para a versão atual do Hibernate.
Alexander Rühl

Respostas:


193

Depende se você está usando JPA ou Hibernate.

A partir da especificação JPA 2.0 , os padrões são:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

E em hibernação, tudo é preguiçoso

ATUALIZAR:

A última versão do Hibernate se alinha com os padrões JPA acima.


11
"E em hibernação, tudo é preguiçoso", aparentemente mudou nas versões recentes. Por favor, veja a resposta de Alexander Rühl abaixo .
Jantar

1
Hibernate é uma das implementações JPA, então uma vez que você está usando o Hibernate, você está usando JPA :)
xenteros

Esta é uma consulta popular. @Ashish Agarwal Você pode atualizar a última linha de sua resposta. Em Hibernate não é preguiçoso para todos agora.
Saurabh Tiwari

Atualizado a postagem com relação ao comportamento do Hibernate mais recente.
M Anouti

Houve uma atualização, alegando que ansioso é o tipo de busca padrão para cada mapeamento, o que é refutado pelo capítulo 11.3 na documentação atual do Hibernate 5.xe na nova 6.x, então desfiz a edição. Além disso, é contra a recomendação não ter avidez automática, pois isso significaria provavelmente selecionar todo o banco de dados ao buscar um único objeto.
Alexander Rühl

51

Eu sei que as respostas estavam corretas no momento de fazer a pergunta - mas já que as pessoas (como eu neste minuto) ainda as encontram se perguntando por que seu WildFly 10 estava se comportando de maneira diferente, eu gostaria de dar uma atualização para o Hibernate 5 atual versão .x:

No Guia do Usuário do Hibernate 5.2 , está descrito no capítulo 11.2. Aplicando estratégias de busca :

A recomendação do Hibernate é marcar estaticamente todas as associações como lazy e usar estratégias de busca dinâmica para avidez. Infelizmente, isso está em desacordo com a especificação JPA, que define que todas as associações um-para-um e muitos-para-um devem ser buscadas avidamente por padrão . O Hibernate, como um provedor JPA, respeita esse padrão.

Portanto, o Hibernate também se comporta como Ashish Agarwal declarado acima para JPA:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(consulte as especificações JPA 2.1 )


E se usarmos a hibernação nativa em vez do JPA impl, ele age da mesma maneira?
jMounir,

@jMounir: Bem, eu não tentei isso, mas como o Hibernate afirma que se comporta como definido no JPA, não vejo por que isso seria diferente ao usar o Hibernate sozinho. Em ambos os casos, pode-se substituir a estratégia padrão.
Alexander Rühl

15

Para responder à sua pergunta, o Hibernate é uma implementação do padrão JPA. O Hibernate tem suas próprias peculiaridades de operação, mas de acordo com os documentos do Hibernate

Por padrão, o Hibernate usa lazy select fetching para coleções e lazy proxy fetching para associações de valor único. Esses padrões fazem sentido para a maioria das associações na maioria dos aplicativos.

Portanto, o Hibernate sempre carregará qualquer objeto usando uma estratégia de busca preguiçosa, não importando o tipo de relacionamento que você declarou. Ele usará um proxy preguiçoso (que deve ser não inicializado, mas não nulo) para um único objeto em um relacionamento um-para-um ou muitos-para-um e uma coleção nula que hidratará com valores quando você tentar acessá-lo .

Deve ser entendido que o Hibernate só tentará preencher esses objetos com valores quando você tentar acessar o objeto, a menos que você especifique fetchType.EAGER.


0

Para associações de valor único, isto é, Um-para-Um e Muitos-para-Um: -
Preguiçoso padrão =
carregamento lento do proxy : - Isso implica que um objeto proxy da entidade associada foi carregado. Isso significa que apenas o id que conecta as duas entidades é carregado para o objeto proxy da entidade associada.
Por exemplo: A e B são duas entidades com associação Muitos para um. isto é: Pode haver vários A's para cada B. Cada objeto de A conterá uma referência de B.
`

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
A relação A conterá colunas (ajuda, lance, ... outras colunas da entidade A).
A relação B conterá colunas (lance, ... outras colunas da entidade B)

Proxy implica que quando A é buscado, apenas id é buscado para B e armazenado em um objeto proxy de B que contém apenas id. O objeto proxy de B é um objeto de uma classe proxy que é uma subclasse de B com apenas campos mínimos. Como o lance já faz parte da relação A, não é necessário disparar uma consulta para obter o lance da relação B. Outros atributos da entidade B são carregados lentamente somente quando um campo diferente de lance é acessado.

Para coleções, isto é, muitos-para-muitos e um-para-muitos: -
Padrão lento = verdadeiro


Observe também que a estratégia de busca (selecionar, juntar etc.) pode substituir o lento. ie: Se lazy = 'true' e fetch = 'join', a busca de A também buscará B ou Bs (no caso de coleções). Você pode entender o motivo se pensar a respeito.
A busca padrão para associação de valor único é "junção".
A busca padrão para coleções é "selecionar". Verifique as duas últimas linhas. Eu deduzi isso logicamente.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.