From e5044c51c1fc7b042a7e1c0e957bfa7fa7cd4558 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Mon, 19 Jun 2017 15:36:14 +0300 Subject: [PATCH] HHH-11186 - Add examples for all Hibernate annotations Document @LazyToOne annotation --- .../topical/bytecode/BytecodeEnhancement.adoc | 1 - .../userguide/appendices/Annotations.adoc | 2 +- .../chapters/domain/associations.adoc | 25 +++ .../OneToOneBidirectionalLazyTest.java | 153 ++++++++++++++++++ 4 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 documentation/src/test/java/org/hibernate/userguide/associations/OneToOneBidirectionalLazyTest.java diff --git a/documentation/src/main/asciidoc/topical/bytecode/BytecodeEnhancement.adoc b/documentation/src/main/asciidoc/topical/bytecode/BytecodeEnhancement.adoc index 7ea2b0fcf2..bbcc95cf3a 100644 --- a/documentation/src/main/asciidoc/topical/bytecode/BytecodeEnhancement.adoc +++ b/documentation/src/main/asciidoc/topical/bytecode/BytecodeEnhancement.adoc @@ -4,7 +4,6 @@ This guide covers Hibernate's ability to enhance an applications domain model, the ways to perform that enhancement and the capabilities introduced into the domain model by the enhancement. - == The capabilities Hibernate will enhance the classes in an application's domain model in order to add one or more of the diff --git a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc index 425c0d8382..bd02785434 100644 --- a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc +++ b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc @@ -960,7 +960,7 @@ FALSE:: Eagerly load the association. This one is not needed since the JPA `Fetc NO_PROXY:: This option will fetch the association lazily while returning real entity object. PROXY:: This option will fetch the association lazily while returning a proxy instead. -//TODO: Add example +See the <> section for more info. [[annotations-hibernate-listindexbase]] ==== `@ListIndexBase` diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/associations.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/associations.adoc index 3e95e80a47..a15aa7ceb0 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/associations.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/associations.adoc @@ -225,6 +225,31 @@ include::{sourcedir}/OneToOneBidirectionalTest.java[tags=associations-one-to-one ---- ==== +[[associations-one-to-one-bidirectional-lazy]] +====== Bidirectional `@OneToOne` lazy association + +Although you might annotate the parent-side association to be fetched lazily, +Hibernate cannot honor this request since it cannot know whether the association is `null` or not. + +The only way to figure out whether there is an associated record on the child side is to fetch the child association using a secondary query. +Because this can lead to N+1 query issues, it's much more efficient to use unidirectional `@OneToOne` associations with the `@MapsId` annotation in place. + +However, if you really need to use a bidirectional association and want to make sure that this is always going to be fetched lazily, +then you need to enable lazy state initialization bytecode enhancement and use the +https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/LazyToOne.html[`@LazyToOne`] annotation as well. + +[[associations-one-to-one-bidirectional-lazy-example]] +.Bidirectional `@OneToOne` lazy parent-side association +==== +[source,java] +---- +include::{sourcedir}/OneToOneBidirectionalLazyTest.java[tags=associations-one-to-one-bidirectional-lazy-example,indent=0] +---- +==== + +For more about how to enable Bytecode enhancement, +see the <>. + [[associations-many-to-many]] ==== `@ManyToMany` diff --git a/documentation/src/test/java/org/hibernate/userguide/associations/OneToOneBidirectionalLazyTest.java b/documentation/src/test/java/org/hibernate/userguide/associations/OneToOneBidirectionalLazyTest.java new file mode 100644 index 0000000000..fca7e71006 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/userguide/associations/OneToOneBidirectionalLazyTest.java @@ -0,0 +1,153 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.userguide.associations; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +import org.hibernate.annotations.LazyToOne; +import org.hibernate.annotations.LazyToOneOption; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Assert; +import org.junit.Test; + +import org.jboss.logging.Logger; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; + +/** + * @author Vlad Mihalcea + */ +public class OneToOneBidirectionalLazyTest extends BaseEntityManagerFunctionalTestCase { + + private static final Logger log = Logger.getLogger( OneToOneBidirectionalLazyTest.class ); + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Phone.class, + PhoneDetails.class, + }; + } + + @Test + public void testLifecycle() { + + } + + //tag::associations-one-to-one-bidirectional-lazy-example[] + @Entity(name = "Phone") + public static class Phone { + + @Id + @GeneratedValue + private Long id; + + @Column(name = "`number`") + private String number; + + @OneToOne( + mappedBy = "phone", + cascade = CascadeType.ALL, + orphanRemoval = true, + fetch = FetchType.LAZY + ) + @LazyToOne( LazyToOneOption.NO_PROXY ) + private PhoneDetails details; + + public Phone() { + } + + public Phone(String number) { + this.number = number; + } + //Getters and setters are omitted for brevity + + //end::associations-one-to-one-bidirectional-lazy-example[] + + public Long getId() { + return id; + } + + public String getNumber() { + return number; + } + + public PhoneDetails getDetails() { + return details; + } + + public void addDetails(PhoneDetails details) { + details.setPhone( this ); + this.details = details; + } + + public void removeDetails() { + if ( details != null ) { + details.setPhone( null ); + this.details = null; + } + } + //tag::associations-one-to-one-bidirectional-lazy-example[] + } + + @Entity(name = "PhoneDetails") + public static class PhoneDetails { + + @Id + @GeneratedValue + private Long id; + + private String provider; + + private String technology; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "phone_id") + private Phone phone; + + public PhoneDetails() { + } + + public PhoneDetails(String provider, String technology) { + this.provider = provider; + this.technology = technology; + } + //Getters and setters are omitted for brevity + + //end::associations-one-to-one-bidirectional-lazy-example[] + + public String getProvider() { + return provider; + } + + public String getTechnology() { + return technology; + } + + public void setTechnology(String technology) { + this.technology = technology; + } + + public Phone getPhone() { + return phone; + } + + public void setPhone(Phone phone) { + this.phone = phone; + } + //tag::associations-one-to-one-bidirectional-lazy-example[] + } + //end::associations-one-to-one-bidirectional-lazy-example[] +}