Hibernate: carregamento lento de um para um, opcional = false

Eu enfrentei o problema que o carregamento lento de um para um não funciona em hibernação. Eu já resolvi isso , mas ainda não entendi direito o que acontece.

Meu código (o carregamento lento não funciona aqui , quando eu puxo Person – Address também é buscado):

@Entity public class Person{ @Id @SequenceGenerator(name = "person_sequence", sequenceName = "sq_person") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence") @Column(name = "id") private long personID; @OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY) private Adress address; //.. getters, setters } @Entity public class Address { @Id @Column(name="id", unique=true, nullable=false) @GeneratedValue(generator="gen") @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="person")) private long personID; @PrimaryKeyJoinColumn @OneToOne private FileInfo person; } 

Mas : se eu adicionar optional=false no relacionamento OneToOne, o carregamento lento funciona bem !

 @OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY) private Adress address; 

Pergunta / input: por favor, explique-me como optional=false anotação optional=false ajuda a alcançar o carregamento lento.

PS Eu li posts post1 e post2 , e entendo porque o OneToOne simples não pode ser preguiçoso, mas eu ainda não consigo entender optional=false magic.

    Se a associação for opcional, o Hibernate não tem como saber se existe um endereço para uma determinada pessoa sem emitir uma consulta. Por isso, não é possível preencher o campo de endereço com um proxy, porque não pode haver referências que façam referência à pessoa e não é possível preenchê-la com null, porque pode haver um endereço referenciando a pessoa.

    Quando você faz a associação obrigatória (ie optional=false ), ela confia em você e assume que existe um endereço, uma vez que a associação é obrigatória. Por isso, preenche diretamente o campo de endereço com um proxy, sabendo que existe um endereço referenciando a pessoa.

    O mais simples é fingir um relacionamento um para muitos. Isso funcionará porque o carregamento lento da coleta é muito mais fácil do que o carregamento lento de uma única propriedade anulável, mas geralmente essa solução é muito inconveniente se você usar consultas JPQL / HQL complexas.

    O outro é usar instrumentação bytecode de tempo de construção. Para mais detalhes, leia a documentação do Hibernate: 19.1.7. Usando a busca de propriedades lazy. Lembre-se de que, neste caso, você deve adicionar a @LazyToOne(LazyToOneOption.NO_PROXY) a uma relação de um para um para torná-la preguiçosa. Definir a busca para LAZY não é suficiente.

    A última solução é usar a instrumentação bytecode de tempo de execução, mas ela funcionará apenas para aqueles que usam o Hibernate como provedor JPA em um ambiente JEE completo (nesse caso, definir ” hibernate.ejb.use_class_enhancer ” como true deve fazer o seguinte: Entity Manager Configuration ) ou use o Hibernate com Spring configurado para fazer tecelagem em tempo de execução (isso pode ser difícil de se conseguir em alguns servidores de aplicativos mais antigos). Neste caso, a @LazyToOne(LazyToOneOption.NO_PROXY) também é necessária.