Eu sou um novato na API Java Persistence e Hibernate.
Qual é a diferença entre FetchType.LAZY
e FetchType.EAGER
na Java Persistence API?
Eu sou um novato na API Java Persistence e Hibernate.
Qual é a diferença entre FetchType.LAZY
e FetchType.EAGER
na Java Persistence API?
Respostas:
Às vezes você tem duas entidades e há um relacionamento entre elas. Por exemplo, você pode ter uma entidade chamada
University
e outra entidade chamadaStudent
e uma Universidade pode ter muitos Estudantes:A entidade Universidade pode ter algumas propriedades básicas, como identificação, nome, endereço etc., além de uma propriedade de coleção chamada estudantes que retorna a lista de estudantes de uma determinada universidade:
Agora, quando você carrega uma universidade a partir do banco de dados, o JPA carrega seus campos de identificação, nome e endereço para você. Mas você tem duas opções para o carregamento dos alunos:
getStudents()
método da universidade .Quando uma universidade tem muitos alunos, não é eficiente carregar todos os seus alunos, especialmente quando eles não são necessários e, em casos semelhantes, você pode declarar que deseja que os alunos sejam carregados quando realmente forem necessários. Isso é chamado de carregamento lento.
Aqui está um exemplo, onde
students
é explicitamente marcado para ser carregado com entusiasmo:E aqui está um exemplo em que
students
é explicitamente marcado para ser carregado preguiçosamente:fonte
getStudents()
), mas às vezes isso não é possível, porque no momento esse método é chamado, a sessão já está fechada e a entidade desanexada. Da mesma forma, às vezes temos uma arquitetura cliente / servidor (por exemplo, cliente Swing / servidor JEE) e as entidades / DTOs são transferidas por fio para o cliente e, novamente, mais frequentemente nesses cenários, o carregamento lento não funciona devido à maneira como as entidades são serializados através do fio.getStudents()
método pela primeira vez, os resultados são armazenados em cache? para que eu possa acessar esses resultados mais rapidamente da próxima vez?Basicamente,
fonte
EAGER
carregar coleções significa que elas são buscadas completamente no momento em que seus pais são buscados. Portanto, se você temCourse
e temList<Student>
, todos os alunos são buscados no banco de dados no momento em queCourse
são buscados.LAZY
por outro lado, significa que o conteúdo doList
é buscado apenas quando você tenta acessá-los. Por exemplo, ligandocourse.getStudents().iterator()
. Chamar qualquer método de acesso noList
iniciará uma chamada ao banco de dados para recuperar os elementos. Isso é implementado criando um Proxy em torno deList
(ouSet
). Portanto, para suas coleções preguiçosas, os tipos de concreto não sãoArrayList
eHashSet
, masPersistentSet
ePersistentList
(ouPersistentBag
)fonte
course.getStudents()
, ele dispara uma consulta SQL (vi no console). No tipo de busca preguiçosa também, acontece a mesma coisa. Então, qual é a diferença?fetchtype = LAZY
padrão, mesmo que tente obter a coleção com o getter hibernete emite um erro dizendo que não pode avaliarEu posso considerar o desempenho e a utilização de memória. Uma grande diferença é que a estratégia de busca do EAGER permite usar o objeto de dados buscado sem sessão. Por quê?
Todos os dados são buscados quando dados marcados com ansiedade no objeto quando a sessão está conectada. No entanto, no caso de estratégia de carregamento lento, o objeto marcado de carregamento lento não recupera dados se a sessão for desconectada (após a
session.close()
instrução). Tudo isso pode ser feito pelo proxy de hibernação. A estratégia ansiosa permite que os dados ainda estejam disponíveis após o encerramento da sessão.fonte
De acordo com meu conhecimento, ambos os tipos de busca dependem de suas necessidades.
FetchType.LAZY
está sob demanda (ou seja, quando solicitamos os dados).FetchType.EAGER
é imediato (ou seja, antes de nossa exigência chegar, estamos buscando desnecessariamente o registro)fonte
Por padrão, para todos os objetos de coleção e mapa, a regra de busca é
FetchType.LAZY
e, para outras instâncias, segue aFetchType.EAGER
política.Em resumo,
@OneToMany
e as@ManyToMany
relações não buscam os objetos relacionados (coleção e mapa) implicitamente, mas a operação de recuperação é em cascata através do campo in@OneToOne
e@ManyToOne
ones.(cortesia: - objectdbcom)
fonte
Ambos
FetchType.LAZY
eFetchType.EAGER
são usados para definir o plano de busca padrão .Infelizmente, você só pode substituir o plano de busca padrão para a busca LAZY. A busca pelo EAGER é menos flexível e pode levar a muitos problemas de desempenho .
Meu conselho é restringir o desejo de tornar suas associações EAGER porque a busca é uma responsabilidade do tempo de consulta. Portanto, todas as suas consultas devem usar a diretiva buscar para recuperar apenas o necessário para o caso de negócios atual.
fonte
Do Javadoc :
Por exemplo, ansioso é mais proativo que preguiçoso. Preguiçoso só acontece no primeiro uso (se o provedor entender a dica), enquanto que coisas ansiosas (podem) são pré-buscadas.
fonte
O
Lazy
tipo de busca é, por padrão, selecionado pelo Hibernate, a menos que você marque explicitamente oEager
tipo de busca. Para ser mais preciso e conciso, a diferença pode ser definida como abaixo.FetchType.LAZY
= Isso não carrega os relacionamentos, a menos que você o invoque pelo método getter.FetchType.EAGER
= Isso carrega todos os relacionamentos.Prós e contras desses dois tipos de busca.
Lazy initialization
melhora o desempenho, evitando cálculos desnecessários e reduzindo os requisitos de memória.Eager initialization
leva mais consumo de memória e a velocidade de processamento é lenta.Dito isto, depende da situação, qualquer uma dessas inicializações pode ser usada.
fonte
getMember
seja chamada que corresponda exatamente ao padrão de nome do membro?Book.java
Subject.java
HibernateUtil.java
Main.java
Verifique o método retrieve () do Main.java. Quando obtivermos Subject, seus listBooks de coleção , anotados com
@OneToMany
, serão carregados lentamente. Mas, por outro lado, a associação de livros relacionada ao assunto da coleção , anotada com@ManyToOne
, carrega rapidamente (por ,[default][1]
para ). Podemos mudar o comportamento colocando fetchType.EAGER em Subject.java ou fetchType.LAZY em Books.java.@ManyToOne
fetchType=EAGER
@OneToMany
@ManyToOne
fonte
Fonte
fonte
Quero acrescentar esta nota ao que "Kyung Hwan Min" disse acima.
Suponha que você esteja usando o Spring Rest com este arquiteto simples:
E você deseja retornar alguns dados para o front-end, se estiver usando
FetchType.LAZY
, receberá uma exceção depois de retornar os dados ao método do controlador, uma vez que a sessão é fechada no Serviço paraJSON Mapper Object
que os dados não possam ser obtidos.Há três opções comuns para resolver esse problema, depende do design, desempenho e desenvolvedor:
FetchType.EAGER
, para que a sessão ainda esteja ativa no método do controlador.FetchType.LAZY
método converter para transferir dados deEntity
outro objeto de dadosDTO
e enviá-los ao controlador, portanto, não haverá exceção se a sessão for fechada.fonte
Olá, anexei 2 fotos para ajudar você a entender isso.
fonte
@ drop-shadow se você estiver usando o Hibernate, você pode chamar
Hibernate.initialize()
quando invocar ogetStudents()
método:fonte
LAZY: Busca as entidades filhas preguiçosamente, ou seja, no momento da busca da entidade pai, apenas busca o proxy (criado pelo cglib ou qualquer outro utilitário) das entidades filhas e, quando você acessa qualquer propriedade da entidade filha, é realmente buscado por hibernação.
EAGER: busca as entidades filho junto com o pai.
Para um melhor entendimento, vá para a documentação do Jboss ou use o
hibernate.show_sql=true
seu aplicativo e verifique as consultas emitidas pelo hibernate.fonte