Hibernate Named Query Examples

A named query is a static HQL or SQL query with a fixed query string and defined either using @NamedQuery annotation or an XML file. We can refer to a named query by its name, in the runtime, when we need to execute it.

Note that Hibernate’s @NamedQuery annotation extends JPA’s @NamedQuery annotation with some additional features.

1. Advantages

The named queries help in grouping the HQL statements in a single place and lately refer to them using pre-configured names whenever we need to use them. This grouping helps largely in code cleanup because these HQL statements are no longer scattered in the whole code.

Apart from the above, there are some more advantages of named queries:

  1. Fail fast: query syntaxes are checked when the SessionFactory is created, making the application fail fast in case of an error.
  2. Reusable: These can be accessed and used from several places in the application which increases re-usability.

Performance-wise named queries do not make much difference, nor put any excessive cost.

  1. The cost of transforming an HQL query to SQL is negligible compared to the cost of actually executing the query.
  2. The memory cost of caching the queries is really small. Remember that Hibernate needs to have all the entities’ meta-data in memory anyway.

2. Creating @NamedQuery

To demonstrate how to declare a named query, we have the DepartmentEntity. We are creating a simple named query that fetches a department by its id.

Named query definition has two important attributes:

  • name: The name of the named query by which it will be located using the Session or EntityManager interface.
  • query: The HQL or SQL statement to get executed in the database.
@NamedQuery(name = "QUERY_GET_DEPARTMENT_BY_ID",
    query = DepartmentEntity.QUERY_GET_DEPARTMENT_BY_ID)
@Entity
public class DepartmentEntity implements Serializable {

  //Constant to refer the query name in other places
  public static final String QUERY_GET_DEPARTMENT_BY_ID
      = "QUERY_GET_DEPARTMENT_BY_ID";

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  private String name;

  //Setters and getters are hidden for brevity
}

Additionally, we can supply more configuration attributes as per our requirements.

@NamedQuery(name = "QUERY_GET_DEPARTMENT_BY_ID",
    query = "from DepartmentEntity d where d.id = :id",
    cacheable = true,
    fetchSize = 1,
    timeout = 1,
    readOnly = true)

3. Grouping with @NamedQueries

If we have multiple named queries for an entity we can group them using the @NamedQueries annotation.

@NamedQueries({
    @NamedQuery(name = "QUERY_GET_DEPARTMENT_BY_ID",
        query = "from DepartmentEntity d where d.id = :id"),
    @NamedQuery(name = "QUERY_UPDATE_DEPARTMENT_BY_ID",
        query = "UPDATE DepartmentEntity d SET d.name=:name where d.id = :id")
})
@Entity
public class DepartmentEntity implements Serializable {

  public static final String QUERY_GET_DEPARTMENT_BY_ID
      = "QUERY_GET_DEPARTMENT_BY_ID";

  public static final String QUERY_UPDATE_DEPARTMENT_BY_ID
      = "QUERY_UPDATE_DEPARTMENT_BY_ID";

  //...
}

4. Executing a Named Query

To execute a named query, we can use the createNamedQuery() method that creates a Query instance. Then we can use a method from Query interface to execute the SQL query.

  @Test
  public void getEntityById() {
    Query query =
        em.createNamedQuery(DepartmentEntity.QUERY_GET_DEPARTMENT_BY_ID)
            .setParameter("id", 1);

    DepartmentEntity dept = (DepartmentEntity) query.getSingleResult();

    Assertions.assertEquals("HR", dept.getName());
  }

5. Using @NamedNativeQuery

The @NamedNativeQuery works very similar to @NamedQuery except we need to write the native SQL statements instead of HQL.

@NamedNativeQueries({
    @NamedNativeQuery(name = "NATIVE_QUERY_GET_DEPARTMENT_BY_ID",
        query = "SELECT * FROM TBL_DEPT d WHERE d.id = :id"),
    @NamedNativeQuery(name = "NATIVE_QUERY_UPDATE_DEPARTMENT_BY_ID",
        query = "UPDATE TBL_DEPT d SET d.name=:name WHERE d.id = :id")
})

The execution of named native queries is pretty much similar to the named queries.

  @Test
  public void updateEntityByIdWithNamedNativeQuery() {
    Query query =
        em.createNamedQuery(DepartmentEntity.NATIVE_QUERY_UPDATE_DEPARTMENT_BY_ID)
            .setParameter("name", "SUPPORT")
            .setParameter("id", 1);

    query.executeUpdate();
    flushAndClear();

    DepartmentEntity dept = em.find(DepartmentEntity.class, 1);

    Assertions.assertEquals("SUPPORT", dept.getName());
  }

6. Conclusion

In this tutorial, we learned to create, group and execute named queries using hibernate. As a best practice we should:

  • Use native queries preferably only for selecting records based on complex conditions. Do not use them excessively, otherwise, there is no use of using ORM over simple JDBC.
  • Remember that result of named queries is not cached in the secondary cache, only the query object itself gets cached.
  • Make a habit of adding a couple of unit testcases whenever we add any named query in code. And run those unit testcases immediately.
  • Fortunately, we can not have two named queries with the same name in hibernate. Hibernate shows fail-fast behavior in this regard and will show errors in the application start-up itself.

Happy Learning !!

Sourcecode on Github

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

9 thoughts on “Hibernate Named Query Examples”

  1. We can’t do like this for Update Query.

    It should be like

    “UPDATE DepartmentEntity d SET d.name=:’Finance’ where d.id = :id”

    Reply
  2. thanx for the great article.. Can we define all the Named Queries at one place like some property file instead of writing in the entity class. thanx

    Reply
      • If it comes to reusability you should avoid the constants and provide a method to call the query and hide all the technical stuff to do it as early as possible. If you use constants – next step would be constants for parameters – you are opening the door for non-compiler-safe use everywhere.

        Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.