diff --git a/documentation/src/main/asciidoc/introduction/Introduction.adoc b/documentation/src/main/asciidoc/introduction/Introduction.adoc index e511794d0b23..c50ed96bcb70 100644 --- a/documentation/src/main/asciidoc/introduction/Introduction.adoc +++ b/documentation/src/main/asciidoc/introduction/Introduction.adoc @@ -498,8 +498,8 @@ Let's hit the code with our favorite thing, the Extract Method refactoring. We o [source,java] ---- -static List findBooksByTitleWithPagination(Session session, - String titlePattern, Page page) { +static List findBooksTitled(Session session, + String titlePattern, Page page) { return session.createSelectionQuery("from Book where title like ?1 order by title", Book.class) .setParameter(1, titlePattern) .setPage(page) @@ -522,9 +522,9 @@ We need a place to put the annotation, so let's move our query method to a new c query = "from Book where title like :title order by title") class Queries { - static List findBooksByTitleWithPagination(Session session, - String titlePattern, Page page) { - return session.createNamedQuery(Queries_._findBooksByTitle_) //type safe reference to the named query + static List findBooksTitled(Session session, + String titlePattern, Page page) { + return session.createQuery(Queries_._findBooksByTitle_) //type safe reference to the named query .setParameter("title", titlePattern) .setPage(page) .getResultList(); @@ -549,7 +549,7 @@ Whatever the case, the code which orchestrates a unit of work usually just calls @Path("books/{titlePattern}") public List findBooks(String titlePattern) { var books = sessionFactory.fromTransaction(session -> - Queries.findBooksByTitleWithPagination(session, titlePattern, + Queries.findBooksTitled(session, titlePattern, Page.page(RESULTS_PER_PAGE, page))); return books.isEmpty() ? Response.status(404).build() : books; } @@ -569,7 +569,7 @@ Suppose we simplify `Queries` to just the following: ---- interface Queries { @HQL("where title like :title order by title") - List findBooksByTitleWithPagination(String title, Page page); + List findBooksTitled(String title, Page page); } ---- @@ -582,7 +582,7 @@ We can call it just like we were previously calling our handwritten version: @Path("books/{titlePattern}") public List findBooks(String titlePattern) { var books = sessionFactory.fromTransaction(session -> - Queries_.findBooksByTitleWithPagination(session, titlePattern, + Queries_.findBooksTitled(session, titlePattern, Page.page(RESULTS_PER_PAGE, page))); return books.isEmpty() ? Response.status(404).build() : books; } @@ -602,7 +602,7 @@ interface Queries { EntityManager entityManager(); @HQL("where title like :title order by title") - List findBooksByTitleWithPagination(String title, Page page); + List findBooksTitled(String title, Page page); } ---- @@ -616,7 +616,7 @@ The `Queries` interface is now considered a _repository_, and we may use CDI to @Path("books/{titlePattern}") @Transactional public List findBooks(String titlePattern) { - var books = queries.findBooksByTitleWithPagination(session, titlePattern, + var books = queries.findBooksTitled(session, titlePattern, Page.page(RESULTS_PER_PAGE, page)); return books.isEmpty() ? Response.status(404).build() : books; } diff --git a/documentation/src/main/asciidoc/introduction/Processor.adoc b/documentation/src/main/asciidoc/introduction/Processor.adoc index ca343468510c..8c42e0ba40f2 100644 --- a/documentation/src/main/asciidoc/introduction/Processor.adoc +++ b/documentation/src/main/asciidoc/introduction/Processor.adoc @@ -572,7 +572,7 @@ This lets us declare which associations of `Book` should be pre-fetched by annot // ---- // interface Queries { // @HQL("from Book where title like :title order by title offset :start fetch first :max rows only") -// List findBooksByTitleWithPagination(String title, int max, int start); +// List findBooksTitled(String title, int max, int start); // } // ---- // @@ -583,7 +583,7 @@ This lets us declare which associations of `Book` should be pre-fetched by annot // [source,java] // ---- // List books = -// Queries_.findBooksByTitleWithPagination(entityManager, titlePattern, +// Queries_.findBooksTitled(entityManager, titlePattern, // RESULTS_PER_PAGE, page*RESULTS_PER_PAGE); // ---- diff --git a/tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/namedquery/Thing.java b/tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/namedquery/Thing.java new file mode 100644 index 000000000000..29abb055972d --- /dev/null +++ b/tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/namedquery/Thing.java @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.namedquery; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.NamedQuery; + +@NamedQuery(name = "#things", + query = "from Thing where name like :name") +@Entity +public class Thing { + @Id @GeneratedValue long id; + String name; +} diff --git a/tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/namedquery/ThingTest.java b/tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/namedquery/ThingTest.java new file mode 100644 index 000000000000..d22a8fd3dff4 --- /dev/null +++ b/tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/namedquery/ThingTest.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.namedquery; + +import jakarta.persistence.EntityManager; +import org.hibernate.processor.test.util.CompilationTest; +import org.hibernate.processor.test.util.WithClasses; +import org.junit.Test; + +import static org.hibernate.processor.test.util.TestUtil.assertMetamodelClassGeneratedFor; +import static org.hibernate.processor.test.util.TestUtil.assertPresenceOfFieldInMetamodelFor; +import static org.hibernate.processor.test.util.TestUtil.assertPresenceOfMethodInMetamodelFor; +import static org.hibernate.processor.test.util.TestUtil.getMetaModelSourceAsString; + +public class ThingTest extends CompilationTest { + @Test @WithClasses( Thing.class ) + public void test() { + System.out.println( getMetaModelSourceAsString( Thing.class) ); + System.out.println( getMetaModelSourceAsString( Thing.class, true) ); + assertMetamodelClassGeneratedFor(Thing.class); + assertMetamodelClassGeneratedFor(Thing.class, true); + assertPresenceOfMethodInMetamodelFor( Thing.class, "things", EntityManager.class, String.class ); + assertPresenceOfFieldInMetamodelFor( Thing.class, "__things_" ); + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java index 05a3b6550550..beaacc8f78af 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java @@ -26,8 +26,10 @@ import java.util.List; import static java.lang.Character.isJavaIdentifierStart; +import static org.hibernate.processor.util.Constants.ENTITY_GRAPH; import static org.hibernate.processor.util.Constants.JAVA_OBJECT; import static org.hibernate.processor.util.Constants.NAMED_QUERY; +import static org.hibernate.processor.util.Constants.TYPED_QUERY_REFERENCE; import static org.hibernate.processor.util.TypeUtils.containsAnnotation; import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror; import static org.hibernate.processor.util.TypeUtils.getAnnotationValue; @@ -107,9 +109,11 @@ private void handleNamedQuery(AnnotationMirror mirror, boolean checkHql) { ProcessorSessionFactory.create( context.getProcessingEnvironment(), context.getEntityNameMappings(), context.getEnumTypesByValue() ) ); - if ( statement instanceof SqmSelectStatement selectStatement ) { + if ( !isJakartaDataStyle() + && statement instanceof SqmSelectStatement selectStatement ) { if ( isQueryMethodName( name ) ) { putMember( name, + // TODO: respect @NamedQuery(resultClass) new NamedQueryMethod( this, selectStatement, @@ -121,13 +125,12 @@ private void handleNamedQuery(AnnotationMirror mirror, boolean checkHql) { ) ); } - if ( !isJakartaDataStyle() - && getAnnotationValue( mirror, "resultClass" ) == null ) { + if ( getAnnotationValue( mirror, "resultClass" ) == null ) { final String resultType = resultType( selectStatement ); if ( resultType != null ) { putMember( "QUERY_" + name, new TypedMetaAttribute( this, name, "QUERY_", resultType, - "jakarta.persistence.TypedQueryReference", hql ) ); + TYPED_QUERY_REFERENCE, hql ) ); } } } @@ -207,11 +210,11 @@ private NameMetaAttribute auxiliaryMember(AnnotationMirror mirror, String prefix // and then we will replace this TypedMetaAttribute return new TypedMetaAttribute( this, name, prefix, resultClass == null ? JAVA_OBJECT : resultClass.getValue().toString(), - "jakarta.persistence.TypedQueryReference", null ); + TYPED_QUERY_REFERENCE, null ); } else if ( "GRAPH_".equals(prefix) ) { return new TypedMetaAttribute( this, name, prefix, getQualifiedName(), - "jakarta.persistence.EntityGraph", null ); + ENTITY_GRAPH, null ); } else { return new NameMetaAttribute( this, name, prefix); diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/util/Constants.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/util/Constants.java index 9cd84c04fb63..8d93474d4767 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/util/Constants.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/util/Constants.java @@ -47,6 +47,9 @@ public final class Constants { public static final String NAMED_ENTITY_GRAPH = "jakarta.persistence.NamedEntityGraph"; public static final String NAMED_ENTITY_GRAPHS = "jakarta.persistence.NamedEntityGraphs"; + public static final String TYPED_QUERY_REFERENCE = "jakarta.persistence.TypedQueryReference"; + public static final String ENTITY_GRAPH = "jakarta.persistence.EntityGraph"; + public static final String HIB_NAMED_QUERY = "org.hibernate.annotations.NamedQuery"; public static final String HIB_NAMED_QUERIES = "org.hibernate.annotations.NamedQueries"; public static final String HIB_NAMED_NATIVE_QUERY = "org.hibernate.annotations.NamedNativeQuery";