From 77ea6186f7eddef25b7cd8978fe11cbc8ddef83f Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Wed, 24 May 2017 17:21:33 +0300 Subject: [PATCH] HHH-11186 - Add examples for all Hibernate annotations Document @OrderBy annotation --- .../userguide/appendices/Annotations.adoc | 2 +- .../chapters/domain/collections.adoc | 35 ++++ ...ordered-by-sql-clause-fetching-example.sql | 12 ++ .../collections/OrderedBySQLTest.java | 176 ++++++++++++++++++ 4 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/extras/collections/collections-customizing-ordered-by-sql-clause-fetching-example.sql create mode 100644 documentation/src/test/java/org/hibernate/userguide/collections/OrderedBySQLTest.java diff --git a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc index 52bb9c7640..7054114d98 100644 --- a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc +++ b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc @@ -1077,7 +1077,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern It differs from the JPA <> annotation because the JPA annotation expects a JPQL order-by fragment, not an SQL directive. -//TODO: Add example +See the <> section for more info. [[annotations-hibernate-paramdef]] ==== `@ParamDef` diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/collections.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/collections.adoc index 083dfb25d5..cdf787eac9 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/collections.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/collections.adoc @@ -410,6 +410,41 @@ include::{extrasdir}/collections-customizing-ordered-list-ordinal-persist-exampl ---- ==== +[[collections-customizing-ordered-by-sql-clause]] +===== Customizing ORDER BY SQL clause + +While the JPA +http://docs.oracle.com/javaee/7/api/javax/persistence/OrderBy.html[`@OrderBy`] annotation allows you to specify the entity attributes used for sorting +when fetching the current annotated collection, the Hibernate specific +https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/OrderBy.html[`@OrderBy`] annotation is used to specify a *SQL* clause instead. + +In the following example, the `@OrderBy` annotations uses the `CHAR_LENGTH` SQL function to order the `Article` entities by the size of their contents. + +[[collections-customizing-ordered-by-sql-clause-mapping-example]] +.`@OrderBy` mapping example +==== +[source,java] +---- +include::{sourcedir}/OrderedBySQLTest.java[tags=collections-customizing-ordered-by-sql-clause-mapping-example,indent=0] +---- +==== + +When fetching the `articles` collection, Hibernate uses the ORDER BY SQL clause provided by the mapping: + +[[collections-customizing-ordered-by-sql-clause-fetching-example]] +.`@OrderBy` fetching example +==== +[source,java] +---- +include::{sourcedir}/OrderedBySQLTest.java[tags=collections-customizing-ordered-by-sql-clause-fetching-example,indent=0] +---- + +[source,sql] +---- +include::{extrasdir}/collections-customizing-ordered-by-sql-clause-fetching-example.sql[] +---- +==== + [[collections-set]] ==== Sets diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/collections/collections-customizing-ordered-by-sql-clause-fetching-example.sql b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/collections/collections-customizing-ordered-by-sql-clause-fetching-example.sql new file mode 100644 index 0000000000..37c2d86732 --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/collections/collections-customizing-ordered-by-sql-clause-fetching-example.sql @@ -0,0 +1,12 @@ +select + a.person_id as person_i4_0_0_, + a.id as id1_0_0_, + a.content as content2_0_1_, + a.name as name3_0_1_, + a.person_id as person_i4_0_1_ +from + Article a +where + a.person_id = ? +order by + CHAR_LENGTH(a.name) desc \ No newline at end of file diff --git a/documentation/src/test/java/org/hibernate/userguide/collections/OrderedBySQLTest.java b/documentation/src/test/java/org/hibernate/userguide/collections/OrderedBySQLTest.java new file mode 100644 index 0000000000..59d05cf6e7 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/userguide/collections/OrderedBySQLTest.java @@ -0,0 +1,176 @@ +/* + * 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.collections; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +import org.hibernate.dialect.H2Dialect; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.RequiresDialect; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; + +/** + * @author Vlad Mihalcea + */ +@RequiresDialect(H2Dialect.class) +public class OrderedBySQLTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Person.class, + Article.class, + }; + } + + @Test + public void testLifecycle() { + doInJPA( this::entityManagerFactory, entityManager -> { + Person person = new Person(); + person.setId( 1L ); + person.setName( "Vlad Mihalcea" ); + + person.addArticle( + new Article( + "High-Performance JDBC", + "Connection Management, Statement Caching, Batch Updates" + ) + ); + person.addArticle( + new Article( + "High-Performance Hibernate", + "Associations, Lazy fetching, Concurrency Control, Second-level Caching" + ) + ); + entityManager.persist( person ); + } ); + doInJPA( this::entityManagerFactory, entityManager -> { + //tag::collections-customizing-ordered-by-sql-clause-fetching-example[] + Person person = entityManager.find( Person.class, 1L ); + assertEquals( + "High-Performance Hibernate", + person.getArticles().get( 0 ).getName() + ); + //end::collections-customizing-ordered-by-sql-clause-fetching-example[] + } ); + } + + //tag::collections-customizing-ordered-by-sql-clause-mapping-example[] + @Entity(name = "Person") + public static class Person { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "person", cascade = CascadeType.ALL) + @org.hibernate.annotations.OrderBy(clause = "CHAR_LENGTH(name) DESC") + private List
articles = new ArrayList<>(); + + //Getters and setters are omitted for brevity + //end::collections-customizing-ordered-by-sql-clause-mapping-example[] + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List
getArticles() { + return articles; + } + + public void addArticle(Article article) { + article.setPerson( this ); + articles.add( article ); + } + //tag::collections-customizing-ordered-by-sql-clause-mapping-example[] + } + + @Entity(name = "Article") + public static class Article { + + @Id + @GeneratedValue + private Long id; + + private String name; + + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + private Person person; + + private Article() { + } + + public Article(String name, String content) { + this.name = name; + this.content = content; + } + + //Getters and setters are omitted for brevity + //end::collections-customizing-ordered-by-sql-clause-mapping-example[] + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + //tag::collections-customizing-ordered-by-sql-clause-mapping-example[] + } + //end::collections-customizing-ordered-by-sql-clause-mapping-example[] +}