@Incubating

Package org.hibernate.annotations.processing

Annotations used to drive annotation processors:
  • @Find is used to generate finder methods using the Metamodel Generator,
  • @HQL and @SQL are used to generate query methods using the Metamodel Generator, and
  • CheckHQL instructs the Query Validator to check all HQL queries in the annotated package or type.

Annotations in this package control Hibernate's compile-time tooling, and depend on the use of the annotation processors in the hibernate-jpamodelgen or query-validator modules. If the appropriate annotation processor is not enabled at build time, these annotations have no effect.

Finder methods and query methods are usually declared by an interface, say Queries, and their implementations are generated into a class whose name follows the convention of the JPA static metamodel, that is, Queries_.

  • If the interface declares a method which returns an EntityManager, Hibernate session, stateless session, or reactive session, the generated class implements the interface, class Queries_ implements Queries, the generated methods are instance methods, and the session must be provided to the class constructor, possibly via dependency injection.
  • Otherwise, if there is no such method, the generated class is non-instantiable, abstract class Queries_, the generated methods are declared static, and the session must be provided as an argument by the caller of the generated methods.

For example, this code defines a DAO-style repository object:

 package org.example;

 import org.hibernate.StatelessSession;
 import org.hibernate.annotations.processing.Find;
 import org.hibernate.annotations.processing.HQL;
 import org.hibernate.query.Order;

 import java.util.List;

 interface BookRepository {

   StatelessSession session();

   @Find
   Book bookByIsbn(String isbn);

   @Find
   List<Book> booksByPublisher(long publisher$id);

   @HQL("where title like :title")
   List<Book> booksByTitle(String title, Order<Book> order);

 }
 

The Metamodel Generator produces this implementation when the interface is compiled:

 package org.example;

 import jakarta.annotation.Generated;
 import jakarta.annotation.Nonnull;
 import jakarta.enterprise.context.Dependent;
 import jakarta.inject.Inject;
 import jakarta.persistence.metamodel.StaticMetamodel;
 import java.util.List;
 import org.hibernate.StatelessSession;
 import org.hibernate.query.Order;

 @Dependent 
 @StaticMetamodel(BookRepository.class) 
 @Generated("org.hibernate.processor.HibernateProcessor")
 public class BookRepository_ implements BookRepository {


    @Override 
    public List<Book> booksByTitle(String title, Order<Book> order) {
         return session.createQuery(BOOKS_BY_TITLE_String, Book.class)
                 .setParameter("title", title)
                 .setOrder(order)
                 .getResultList();
    }

    @Override 
    public Book bookByIsbn(@Nonnull String isbn) {
         return session.get(Book.class, isbn);
    }

     private final @Nonnull StatelessSession session;

    @Inject 
    public BookRepository_(@Nonnull StatelessSession session) {
         this.session = session;
    }

    public @Nonnull StatelessSession session() {
         return session;
    }

    @Override 
    public List<Book> booksByPublisher(long publisher$id) {
         var builder = session.getFactory().getCriteriaBuilder();
         var query = builder.createQuery(Book.class);
         var entity = query.from(Book.class);
         query.where(
                 builder.equal(entity.get(Book_.publisher).get(Publisher_.id), publisher$id)
         );
         return session.createQuery(query).getResultList();
    }

     static final String BOOKS_BY_TITLE_String = "where title like :title";

 }
 

The exact annotations included in the generated code depend on the libraries available during compilation. The code above was produced with CDI and Jakarta annotations on the build path, and so the repository is an injectable CDI bean and uses @Nonnull to indicate required parameters.