Primeiro, alguns esclarecimentos à resposta do KLE :
A associação individual irrestrita (anulável) é a única que não pode ser proxy sem a instrumentação de bytecode. A razão para isso é que a entidade proprietária DEVE saber se a propriedade da associação deve conter um objeto proxy ou NULL e não pode determinar isso observando as colunas da tabela base, porque normalmente um a um é mapeado através de PK compartilhada. precisa ser buscado de qualquer maneira, tornando o proxy inútil. Aqui está uma explicação mais detalhada .
associações muitos-para-um (e um-para-muitos, obviamente) não sofrem com esse problema. A entidade proprietária pode facilmente verificar seu próprio FK (e, no caso de um para muitos, o proxy de coleção vazio é criado inicialmente e preenchido sob demanda), para que a associação seja preguiçosa.
Substituir um para um por um para muitos nunca é uma boa ideia. Você pode substituí-lo por muitos exclusivos para muitos, mas existem outras opções (possivelmente melhores).
Rob H. tem um ponto válido, no entanto, talvez você não consiga implementá-lo, dependendo do seu modelo (por exemplo, se sua associação um a um é anulável).
Agora, no que diz respeito à pergunta original:
A) @ManyToOne(fetch=FetchType.LAZY)
deve funcionar muito bem. Tem certeza de que não está sendo substituído na própria consulta? É possível especificar join fetch
no HQL e / ou definir explicitamente o modo de busca via API de critérios, o que teria precedência sobre a anotação de classe. Se esse não for o caso e você ainda estiver com problemas, publique suas classes, consulte o SQL resultante para obter uma conversa mais direta.
B) @OneToOne
é mais complicado. Se definitivamente não for anulável, siga a sugestão de Rob H. e especifique-a da seguinte forma:
@OneToOne(optional = false, fetch = FetchType.LAZY)
Caso contrário, se você puder alterar seu banco de dados (adicionar uma coluna de chave estrangeira à tabela do proprietário), faça-o e mapeie-o como "unido":
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="other_entity_fk")
public OtherEntity getOther()
e em OtherEntity:
@OneToOne(mappedBy = "other")
public OwnerEntity getOwner()
Se você não pode fazer isso (e não pode viver com a busca ansiosa), a instrumentação bytecode é sua única opção. Eu tenho que concordar com CPerkins , no entanto - se você tem 80 !!! se une devido a associações OneToOne, você tem problemas maiores que este :-)
one-to-one
com uma fórmula comoselect other_entity.id from other_entity where id = other_entity.id
. Obviamente, isso não é ideal para performances de consulta.Para que o carregamento lento funcione em mapeamentos um-para-um anuláveis, você precisa permitir que o hibernate compile a instrumentação de tempo e adicione
@LazyToOne(value = LazyToOneOption.NO_PROXY)
a à relação um-para-um.Exemplo de mapeamento:
Extensão de arquivo Ant Build do exemplo (para executar a instrumentação de tempo de compilação do Hibernate):
fonte
LazyToOneOption.NO_PROXY
e nãoLazyToOneOption.PROXY
?A idéia básica por trás dos XToOnes no Hibernate é que eles não são preguiçosos na maioria dos casos.
Uma razão é que, quando o Hibernate precisa decidir colocar um proxy (com o ID) ou um valor nulo,
ele precisa procurar na outra tabela para participar. O custo de acessar a outra tabela no banco de dados é significativo; portanto, é possível buscar os dados dessa tabela naquele momento (comportamento não preguiçoso), em vez de buscá-lo em uma solicitação posterior que exigiria um segundo acesso ao mesma mesa.
Editado: para detalhes, consulte a resposta de ChssPly76 . Este é menos preciso e detalhado, não tem nada a oferecer. Obrigado ChssPly76.
fonte
Aqui está algo que está funcionando para mim (sem instrumentação):
Em vez de usar
@OneToOne
nos dois lados, eu uso@OneToMany
na parte inversa do relacionamento (aquele commappedBy
). Isso torna a propriedade uma coleção (List
no exemplo abaixo), mas eu a traduzo em um item no getter, tornando-a transparente para os clientes.Essa configuração funciona preguiçosamente, ou seja, as seleções são feitas apenas quando
getPrevious()
ougetNext()
são chamadas - e apenas uma seleção para cada chamada.A estrutura da tabela:
A classe:
fonte
Como expliquei neste artigo , a menos que você esteja usando o Bytecode Enhancement , não poderá buscar preguiçosamente a
@OneToOne
associação do lado dos pais .No entanto, na maioria das vezes, você nem precisa da associação do lado dos pais se usar
@MapsId
no lado do cliente:Com
@MapsId
, aid
propriedade na tabela filha serve como Chave Primária e Chave Externa para a Chave Primária da tabela pai.Portanto, se você tiver uma referência à
Post
entidade pai , poderá buscar facilmente a entidade filha usando o identificador da entidade pai:Dessa forma, você não terá problemas de consulta N + 1 que podem ser causados pela
mappedBy
@OneToOne
associação no lado pai.fonte
Nos mapeamentos XML nativos do Hibernate, você pode fazer isso declarando um mapeamento individual com o atributo restrito definido como true. Não tenho certeza do que é equivalente à anotação Hibernate / JPA, e uma rápida pesquisa no documento não forneceu resposta, mas espero que isso lhe dê uma pista para continuar.
fonte
@OneToOne(optional=false,fetch=FetchMode.LAZY)
Como já foi perfeitamente explicado por ChssPly76, os proxies do Hibernate não ajudam com associações um-a-um sem restrições (anuláveis), MAS, há um truque explicado aqui para evitar a configuração da instrumentação. A idéia é enganar o Hibernate que a classe de entidade que queremos usar já foi instrumentada: você a instrumenta manualmente no código-fonte. É fácil! Eu o implementei com o CGLib como provedor de bytecode e ele funciona (verifique se você configurou lazy = "no-proxy" e fetch = "select", não "join", no seu HBM).
Eu acho que essa é uma boa alternativa para a instrumentação real (quero dizer automática) quando você tem apenas uma relação anulável de um para um que deseja tornar preguiçosa. A principal desvantagem é que a solução depende do provedor de bytecode que você está usando, portanto, comente sua classe com precisão, pois poderá ser necessário alterar o fornecedor de bytecode no futuro; é claro, você também está modificando seu bean de modelo por uma razão técnica e isso não está correto.
fonte
Essa pergunta é bastante antiga, mas com o Hibernate 5.1.10, há uma nova solução melhor e mais confortável.
O carregamento lento funciona, exceto para o lado pai de uma associação @OneToOne. Isso ocorre porque o Hibernate não tem outra maneira de saber se atribui um nulo ou um proxy a essa variável. Mais detalhes você pode encontrar neste artigo
fonte
Se a relação não deve ser bidirecional, um @ElementCollection pode ser mais fácil do que usar uma coleção lenta do One2Many.
fonte