From 67b01b50044767e719bb6330dcaf64f0073c7be5 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Mon, 19 Jun 2017 17:16:26 +0300 Subject: [PATCH] HHH-11186 - Add examples for all Hibernate annotations Document Hibernate @NativeQuery and @NamedNativeQuery annotation --- documentation/documentation.gradle | 2 +- .../userguide/appendices/Annotations.adoc | 4 +- .../userguide/chapters/query/hql/HQL.adoc | 15 ++++++ .../chapters/query/native/Native.adoc | 21 +++++++++ .../userguide/model/PersonPhoneCount.java | 30 ++++++++++++ .../org/hibernate/userguide/model/Phone.java | 46 +++++++++++++++++++ .../org/hibernate/userguide/hql/HQLTest.java | 13 ++++++ .../org/hibernate/userguide/sql/SQLTest.java | 16 +++++++ 8 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 documentation/src/main/java/org/hibernate/userguide/model/PersonPhoneCount.java diff --git a/documentation/documentation.gradle b/documentation/documentation.gradle index 5901b2787d..49ff5fca04 100644 --- a/documentation/documentation.gradle +++ b/documentation/documentation.gradle @@ -51,11 +51,11 @@ dependencies { asciidoclet 'org.asciidoctor:asciidoclet:0.+' compile( libraries.jpa ) + compile( project( ':hibernate-core' ) ) compile( project( ':hibernate-jpamodelgen' ) ) testCompile( 'org.apache.commons:commons-lang3:3.4' ) - testCompile( project(':hibernate-core') ) testCompile( project(':hibernate-ehcache') ) testCompile( project(':hibernate-spatial') ) testCompile( project(path: ':hibernate-core', configuration: 'tests') ) diff --git a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc index bd02785434..5c25177fe8 100644 --- a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc +++ b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc @@ -1018,7 +1018,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern - what SQL-level comment should be sent to the database - if the query is read-only, hence it does not store the resulted entities into the currently running Persistence Context -//TODO: Add example +See the <> section for more info. [[annotations-hibernate-namedqueries]] ==== `@NamedQueries` @@ -1039,7 +1039,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern - what SQL-level comment should be sent to the database - if the query is read-only, hence it does not store the resulted entities into the currently running Persistence Context -//TODO: Add example +See the <> section for more info. [[annotations-hibernate-nationalized]] ==== `@Nationalized` diff --git a/documentation/src/main/asciidoc/userguide/chapters/query/hql/HQL.adoc b/documentation/src/main/asciidoc/userguide/chapters/query/hql/HQL.adoc index 5951ea2909..1c46a1c2cb 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/query/hql/HQL.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/query/hql/HQL.adoc @@ -71,6 +71,21 @@ include::{sourcedir}/HQLTest.java[tags=jpql-api-named-query-example, indent=0] ---- ==== +Hibernate offers a specific +https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/NamedQuery.html[`@NamedQuery`] annotation +which provides ways to configure various query features, like flush mode, cacheability, time out interval. + +[[jpql-api-hibernate-named-query-example]] +.Obtaining a Hibernate `Query` or a `TypedQuery` reference for a named query +==== +[source, JAVA, indent=0] +---- +include::{modeldir}/Phone.java[tags=jpql-api-hibernate-named-query-example, indent=0] + +include::{sourcedir}/HQLTest.java[tags=jpql-api-hibernate-named-query-example, indent=0] +---- +==== + The `Query` interface can then be used to control the execution of the query. For example, we may want to specify an execution timeout or control caching. diff --git a/documentation/src/main/asciidoc/userguide/chapters/query/native/Native.adoc b/documentation/src/main/asciidoc/userguide/chapters/query/native/Native.adoc index 62e8a25747..48fe82f29e 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/query/native/Native.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/query/native/Native.adoc @@ -536,6 +536,27 @@ include::{sourcedir}/SQLTest.java[tags=sql-hibernate-multiple-scalar-values-dto- ---- ==== +You can also use the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/NamedNativeQuery.html[`@NamedNativeQuery`] Hibernate annotation +to customize the named query using various configurations such as fetch mode, cacheability, time out interval. + +[[sql-multiple-scalar-values-dto-NamedNativeQuery-hibernate-example]] +.Multiple scalar values using `ConstructorResult` and Hibernate `NamedNativeQuery` +==== +[source, JAVA, indent=0] +---- +include::{modeldir}/Phone.java[tags=sql-multiple-scalar-values-dto-NamedNativeQuery-hibernate-example] +---- +==== + +[[sql-hibernate-multiple-scalar-values-dto-hibernate-named-query-example]] +.Hibernate `NamedNativeQuery` named native query selecting multiple scalar values into a DTO +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/SQLTest.java[tags=sql-hibernate-multiple-scalar-values-dto-hibernate-named-query-example] +---- +==== + [[sql-entity-named-queries]] ==== Named SQL queries selecting entities diff --git a/documentation/src/main/java/org/hibernate/userguide/model/PersonPhoneCount.java b/documentation/src/main/java/org/hibernate/userguide/model/PersonPhoneCount.java new file mode 100644 index 0000000000..e8cbe902c6 --- /dev/null +++ b/documentation/src/main/java/org/hibernate/userguide/model/PersonPhoneCount.java @@ -0,0 +1,30 @@ +/* + * 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.model; + +/** + * @author Vlad Mihalcea + */ +public class PersonPhoneCount { + + private final String name; + + private final Number phoneCount; + + public PersonPhoneCount(String name, Number phoneCount) { + this.name = name; + this.phoneCount = phoneCount; + } + + public String getName() { + return name; + } + + public Number getPhoneCount() { + return phoneCount; + } +} diff --git a/documentation/src/main/java/org/hibernate/userguide/model/Phone.java b/documentation/src/main/java/org/hibernate/userguide/model/Phone.java index 29ad69a985..c4dc21f5ef 100644 --- a/documentation/src/main/java/org/hibernate/userguide/model/Phone.java +++ b/documentation/src/main/java/org/hibernate/userguide/model/Phone.java @@ -13,21 +13,67 @@ import java.util.List; import java.util.Map; import javax.persistence.CascadeType; import javax.persistence.Column; +import javax.persistence.ColumnResult; +import javax.persistence.ConstructorResult; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.EntityResult; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; +import javax.persistence.FieldResult; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.MapKey; import javax.persistence.MapKeyTemporal; import javax.persistence.OneToMany; +import javax.persistence.SqlResultSetMapping; import javax.persistence.TemporalType; +import org.hibernate.annotations.NamedNativeQueries; +import org.hibernate.annotations.NamedNativeQuery; +import org.hibernate.annotations.NamedQueries; +import org.hibernate.annotations.NamedQuery; + /** * @author Vlad Mihalcea */ +//tag::jpql-api-hibernate-named-query-example[] +@NamedQueries({ + @NamedQuery( + name = "get_phone_by_number", + query = "select p " + + "from Phone p " + + "where p.number = :number", + timeout = 1, + readOnly = true + ) +}) +//end::jpql-api-hibernate-named-query-example[] +//tag::sql-multiple-scalar-values-dto-NamedNativeQuery-hibernate-example[] +@NamedNativeQueries({ + @NamedNativeQuery( + name = "get_person_phone_count", + query = "SELECT pr.name AS name, count(*) AS phoneCount " + + "FROM Phone p " + + "JOIN Person pr ON pr.id = p.person_id " + + "GROUP BY p.person_id", + resultSetMapping = "person_phone_count", + timeout = 1, + readOnly = true + ), +}) +@SqlResultSetMapping( + name = "person_phone_count", + classes = @ConstructorResult( + targetClass = PersonPhoneCount.class, + columns = { + @ColumnResult(name = "name"), + @ColumnResult(name = "phoneCount") + } + ) +) +//end::sql-multiple-scalar-values-dto-NamedNativeQuery-hibernate-example[] //tag::hql-examples-domain-model-example[] @Entity public class Phone { diff --git a/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java b/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java index 6458ca26a7..c00dec32c7 100644 --- a/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java @@ -584,6 +584,19 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase { }); } + @Test + public void test_jpql_api_hibernate_named_query_example() { + doInJPA( this::entityManagerFactory, entityManager -> { + //tag::jpql-api-hibernate-named-query-example[] + Phone phone = entityManager + .createNamedQuery( "get_phone_by_number", Phone.class ) + .setParameter( "number", "123-456-7890" ) + .getSingleResult(); + //end::jpql-api-hibernate-named-query-example[] + assertNotNull( phone ); + }); + } + @Test public void test_jpql_api_basic_usage_example() { doInJPA( this::entityManagerFactory, entityManager -> { diff --git a/documentation/src/test/java/org/hibernate/userguide/sql/SQLTest.java b/documentation/src/test/java/org/hibernate/userguide/sql/SQLTest.java index e6096080e1..26f937ee97 100644 --- a/documentation/src/test/java/org/hibernate/userguide/sql/SQLTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/sql/SQLTest.java @@ -29,6 +29,7 @@ import org.hibernate.userguide.model.CreditCardPayment; import org.hibernate.userguide.model.Partner; import org.hibernate.userguide.model.Person; import org.hibernate.userguide.model.PersonNames; +import org.hibernate.userguide.model.PersonPhoneCount; import org.hibernate.userguide.model.Phone; import org.hibernate.userguide.model.PhoneType; import org.hibernate.userguide.model.WireTransferPayment; @@ -676,6 +677,21 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase { }); } + @Test + public void test_sql_hibernate_multiple_scalar_values_dto_hibernate_named_query_example() { + doInJPA( this::entityManagerFactory, entityManager -> { + Session session = entityManager.unwrap( Session.class ); + //tag::sql-hibernate-multiple-scalar-values-dto-hibernate-named-query-example[] + List personNames = session.getNamedNativeQuery( + "get_person_phone_count") + .getResultList(); + //end::sql-hibernate-multiple-scalar-values-dto-hibernate-named-query-example[] + assertEquals(2, personNames.size()); + assertEquals(1, personNames.stream().filter( person -> person.getName().equals( "John Doe" ) ).map( PersonPhoneCount::getPhoneCount ).findAny().get().intValue()); + assertEquals(2, personNames.stream().filter( person -> person.getName().equals( "Mrs. John Doe" ) ).map( PersonPhoneCount::getPhoneCount ).findAny().get().intValue()); + }); + } + @Test public void test_sql_jpa_entity_named_query_example() { doInJPA( this::entityManagerFactory, entityManager -> {