2020-03-21

Hibernate - HQL and JPQL Query API (JPA Query API)

When using Hibernate, you can execute entity queries either via JPA or the Hibernate-specific API. the query API was also merged, and now the Hibernate org.hibernate.query.Query interface extends the JPA javax.persistence.Query.

Next, we are going to see how the query API differs between the standard JPA interfaces and the Hibernate-specific API.

JPA Query API

In JPA, the query is represented by javax.persistence.Query or javax.persistence.TypedQuery as obtained from the EntityManager. The create an inline Query or TypedQuery, you need to use the EntityManager#createQuery method. For named queries, the EntityManager#createNamedQuery method is needed.

Obtaining a JPA Query or a TypedQuery reference

Query query = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name"
);

TypedQuery<Person> typedQuery = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name", Person.class
);

Obtaining a JPA Query or a TypedQuery reference for a named query

@NamedQuery(
    name = "get_person_by_name",
    query = "select p from Person p where name = :name"
)

Query query = entityManager.createNamedQuery( "get_person_by_name" );

TypedQuery<Person> typedQuery = entityManager.createNamedQuery(
"get_person_by_name", Person.class
);
Hibernate offers a specific @NamedQuery annotation which provides ways to configure various query features, like flush mode, cacheability, time out interval.

Obtaining a Hibernate Query or a TypedQuery reference for a named query

@NamedQueries({
    @NamedQuery(
        name = "get_phone_by_number",
        query = "select p " +
                "from Phone p " +
                "where p.number = :number",
        timeout = 1,
        readOnly = true
    )
})

Phone phone = entityManager
.createNamedQuery( "get_phone_by_number", Phone.class )
.setParameter( "number", "123-456-7890" )
.getSingleResult();
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.

Basic JPA Query usage

Query query = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name" )
// timeout - in milliseconds
.setHint( "javax.persistence.query.timeout", 2000 )
// flush only at commit time
.setFlushMode( FlushModeType.COMMIT );


JPA name parameter binding

Query query = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name" )
.setParameter( "name", "J%" );

// For generic temporal field types (e.g. `java.util.Date`, `java.util.Calendar`)
// we also need to provide the associated `TemporalType`
Query query = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.createdOn > :timestamp" )
.setParameter( "timestamp", timestamp, TemporalType.DATE );

 JPA positional parameter binding

Query query = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like ?1" )
.setParameter( 1, "J%" );

JPA getResultList() result

List<Person> persons = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name" )
.setParameter( "name", "J%" )
.getResultList();

JPA getResultList() result

List<Person> persons = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name" )
.setParameter( "name", "J%" )
.getResultList();

No comments:

Post a Comment