Hibernate Named Query - @NamedQuery, @NamedQueries, @NamedNativeQuery, and @NamedNativeQueries

In Hibernate, a named query is a JPQL or SQL expression with a predefined unchangeable query string. You can define a named query either in Hibernate mapping file or in an Entity class.
In this tutorial, we will demonstrate the usage of @NamedQuery, @NamedQueries, @NamedNativeQuery, and @NamedNativeQueries annotations to define named queries.
Annotations @NamedQuery and @NamedQueries are used for HQL or JPQL expression whereas @NamedNativeQuery and @NamedNativeQueries are used for native SQL expression.

Named Query Overview

Basically, named queries in Hibernate is a technique to group the HQL statements in a single location, and later refer to them by some name whenever they need to use them. It helps largely in code cleanup because these HQL statements are no longer scattered in the whole code.
Apart from the above, below are some minor advantages of named queries:
  1. Fail fast: Their syntax is checked when the session factory is created, making the application fail fast in case of an error.
  2. Reusable: They can be accessed and used from several places which increases reusability.
The following is an example of the definition of a named query in the JPQL/HQL:
    @NamedQuery(
            name="findAllCustomersWithName",
            query="SELECT c FROM Customer c WHERE c.name LIKE :custName"
    )
Named query definition has two important attributes:
  • name: The name attribute of a named query by which it will be located using hibernate session.
  • query: Here you give the HQL statement to get executed in the database.

Hibernate Named Query Step-By-Step Tutorial

This tutorial shows you how to use the named query annotations such as @NamedQuery and @NamedQueries in Hibernate application.

Technologies and tools used

  • Hibernate 6.1.7.Final
  • IDE - Eclipse
  • Maven 3.5.3
  • JavaSE 17
  • MySQL - 8.0.32

Create a Simple Maven Project

Use the How to Create a Simple Maven Project in Eclipse article to create a simple Maven project in Eclipse IDE.

2. Project Directory Structure

The project directory structure for your reference - 

3. Add jar Dependencies to pom.xml

<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>net.javaguides.hibernate</groupId>
        <artifactId>hibernate-tutorial</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>hibernate-named-query-example</artifactId>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.1.7.Final</version>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Create a Hibernate configuration file - Java Configuration

The HibernateUtil Java configuration file contains information about the database and mapping file.
Let's create a HibernateUtil file and write the following code in it.
package net.javaguides.hibernate.util;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;

import net.javaguides.hibernate.entity.Student;

public class HibernateUtil {
    private static SessionFactory sessionFactory;
    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                Configuration configuration = new Configuration();

                // Hibernate settings equivalent to hibernate.cfg.xml's properties
                Properties settings = new Properties();
                settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
                settings.put(Environment.URL, "jdbc:mysql://localhost:3306/hibernate_db?useSSL=false");
                settings.put(Environment.USER, "root");
                settings.put(Environment.PASS, "root");

                settings.put(Environment.SHOW_SQL, "true");

                settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");

                settings.put(Environment.HBM2DDL_AUTO, "create-drop");

                configuration.setProperties(settings);

                configuration.addAnnotatedClass(Student.class);

                ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties()).build();

                sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return sessionFactory;
    }
}

Using @NamedQuery and @NamedQueries Annotations

Let's create a Student entity class and annotate it with the @NamedQuery and @NamedQueries annotation for using single or multiple-named HQL/JPQL query expressions as follows.
package net.javaguides.hibernate.entity;

import jakarta.persistence.*;

@Entity
@Table(name = "student")

//Using @NamedQuery for single JPQL or HQL
@NamedQuery(name = "GET_STUDENTS_COUNT", query = "select count(1) from Student")

//Using @NamedQueries for multiple JPQL or HQL
@NamedQueries({ @NamedQuery(name = "GET_STUDENT_BY_ID", query = "from Student where id=:id"),
		@NamedQuery(name = "GET_ALL_STUDENTS", query = "from Student") })
public class Student {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	private int id;

	@Column(name = "first_name")
	private String firstName;

	@Column(name = "last_name")
	private String lastName;

	@Column(name = "email")
	private String email;

	public Student() {

	}

	public Student(String firstName, String lastName, String email) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.email = email;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
	}

}

Using Named Query for JPQL

Now, create a main class to execute the named query using the Session.createNamedQuery() method:
package net.javaguides.hibernate;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import net.javaguides.hibernate.entity.Student;
import net.javaguides.hibernate.util.HibernateUtil;

public class NamedNativeQueryExample {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

        saveStudent();

        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            // Executing named queries

            List < Object > totalStudents = session.createNamedQuery("GET_STUDENTS_COUNT").getResultList();
            System.out.println("Total Students: " + totalStudents.get(0));

            List < Object > student = session.createNamedQuery("GET_STUDENT_BY_ID").setParameter("id", 1).getResultList();

            System.out.println(student.get(0));

            List < Student > students = session.createNamedQuery("GET_ALL_STUDENTS", Student.class).getResultList();
            for (Student student1: students) {
                System.out.println("ID : " + student1.getId() + " \tNAME : " + student1.getFirstName());
            }

            transaction.commit();

        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }

    }

    private static void saveStudent() {
        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {

            // start a transaction
            transaction = session.beginTransaction();
            // create new student
            Student student = new Student("Ramesh", "Fadatare", "[email protected]");
            // save the student object
            session.persist(student);
            // commit transaction
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }
    }
}

Using @NamedNativeQuery and @NamedNativeQueries Annotations

Let's create a Student entity class and annotate it with the @NamedNativeQuery and @NamedNativeQueries annotation for using single or multiple-named native SQL query expressions as follows.
package net.javaguides.hibernate.entity;

import jakarta.persistence.*;

@Entity
@Table(name = "student")

@NamedNativeQuery(name = "GET_STUDENTS_COUNT", query = "select count(1) from student")

@NamedNativeQueries({
    @NamedNativeQuery(name = "GET_STUDENT_BY_ID", query = "select * from student where id=:id"),
    @NamedNativeQuery(name = "GET_ALL_STUDENTS", query = "select * from student", resultClass = Student.class)
})
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    public Student() {

    }

    public Student(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Student [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
    }
}
Note that we used  @NamedNativeQuery and @NamedNativeQueries annotations to define named queries with native SQL statements.

Using Named Query for Native SQL Statements

package net.javaguides.hibernate;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import net.javaguides.hibernate.entity.Student;
import net.javaguides.hibernate.util.HibernateUtil;

public class NamedNativeQueryExample {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

        saveStudent();

        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            // Executing named queries

            List < Object > totalStudents = session.createNamedQuery("GET_STUDENTS_COUNT").getResultList();
            System.out.println("Total Students: " + totalStudents.get(0));

            List < Object > student = session.createNamedQuery("GET_STUDENT_BY_ID").setParameter("id", 1).getResultList();

            System.out.println(student.get(0));

            List < Student > students = session.createNamedQuery("GET_ALL_STUDENTS", Student.class).getResultList();
            for (Student student1: students) {
                System.out.println("ID : " + student1.getId() + " \tNAME : " + student1.getFirstName());
            }

            transaction.commit();

        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }

    }

    private static void saveStudent() {
        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {

            // start a transaction
            transaction = session.beginTransaction();
            // create new student
            Student student = new Student("Ramesh", "Fadatare", "[email protected]");
            // save the student object
            session.persist(student);
            // commit transaction
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        }
    }
}

GitHub Repository

The complete source code of this article available on my GitHub Repository - https://github.com/RameshMF/Hibernate-ORM-Tutorials

Conclusion

In this tutorial, we demonstrated the usage of @NamedQuery, @NamedQueries, @NamedNativeQuery, and @NamedNativeQueries annotations to define named queries.

You can learn more about Hibernate ORM Framework at Hibernate Tutorial

Comments