Hello everyone,

Greetings today!

Today we'll explore NamedQuery with JPA and Hibernate, so let's get started.

What is NamedQuery: NamedQuery is a way through which we can define a query over an entity class with some name assigned to it which can be used in the repository layer to refer to a query, so instead of writing queries in the repository layer we can group queries in entity class which makes our repository layer code more readable and maintainable.

Note-NamedQuery is compiled and validated on application start-up which makes our application fail fast when there is an error in the query.

Disadvantages of NamedQuery: Named queries cannot be customized at runtime, but you can pass parameters to NamedQuery at runtime.

Defining NamedQuery

We can define NamedQuery over entity class using @javax.persistence.NamedQuery annotation, we need to specify 2 properties name and query, let's see with an example.

@NamedQuery(name = "findByRollNo",query = "Select s from Student s")

We can pass parameters at runtime as shown below using:parameterName

@Entity
@NamedQuery(name = "findByRollNo",
	query = "Select s from Student s where rollNo=:rollNo")
public class Student {

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

    private String name;

    private String standard;

    private String address;

    private String emailId;
}

We need to set the parameterName value at runtime in the above example we need to set the value of rollNo.

Calling NamedQuery Using JPA

For this, we need to use EntityManager's createNamedQuery method as shown below

TypedQuery<Student> typedQuery=entityManager.createNamedQuery("findByRollNo", Student.class); 

We can set parameter values using setParameter on the typed query.

typedQuery.setParameter("rollNo",rollNo);

@Repository
@Transactional
public class StudentRepository {

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private SessionFactory sessionFactory;

    public Optional<Student> findByRollNo(Integer rollNo){
        TypedQuery<Student> typedQuery=entityManager
         .createNamedQuery("findByRollNo", Student.class);
        
        typedQuery.setParameter("rollNo",rollNo);
        return typedQuery.getResultStream().findFirst();
    }
    

Calling NamedQuery With Hibernate

With hibernate, we need to use a session object instead of an entity manager to refer to the named query we defined in the entity class as shown below.


@Repository
@Transactional
public class StudentRepository {

    @Autowired
    private SessionFactory sessionFactory;

    public Optional<Student> findByEmailId(String emailId){
        Session session = sessionFactory.openSession();
        Query<Student> query = session
         .createNamedQuery("findByEmailId", Student.class);
        
        query.setParameter("emailId",emailId);
        return query.getResultStream().findFirst();
    }
    

We can combine multiple NamedQuery under 1 annotation over entity class to make code more readable using @NamedQueries of javax.persistence as shown below

@NamedQueries({

@NamedQuery(name = "findByRollNo",query = "Select s from Student s where rollNo=:rollNo"),

 @NamedQuery(name = "findByEmailId",query = "Select s from Student s where emailId=:emailId")

})

Define Named Native Query 

For native query, we can use @NamedNativeQuery of javax.persistence as shown below

@NamedNativeQuery(name = "findByName",query = "Select * from Student s where name=:name",resultClass = Student.class)

Note: We need to define the result class with the native query in the entity class for mapping the result of the custom query to the Student class.

Calling Named Native Query

Calling a named native query is similar to how we can call Named JPA Query as shown below
@Repository
@Transactional
public class StudentRepository {

    @Autowired
    private EntityManager entityManager;

	public Optional findByName(String name){
        TypedQuery typedQuery=entityManager
        	.createNamedQuery("findByName", Student.class);
        
        typedQuery.setParameter("name",name);
        return typedQuery.getResultStream().findFirst();
        
    }

So we have seen how we can define named queries, and call them with JPA and Hibernate if you have any questions please post in the comments.

Thanks 
Enjoy your learning!