How to use JPA Native Query in Spring Boot applications

Hibernate and JPA can both execute native SQL statements against a Database. In this tutorial we will learn how to map SQL native queries in Spring Boot applications.

Native Queries in a nutshell

Firstly, the simplest way to run a native SQL Query is to use the createNativeQuery() method of the EntityManager interface, passing in the query string and the entity type that will be returned.

public List<Customer> findAllCustomersNative() {
        Query query = em.createNativeQuery("SELECT * from customer",Customer.class);
        List<Customer> customerList = query.getResultList();
        return customerList;

You can also leverage native SQL for named queries by defining a @NamedNativeQuery annotation on the top of your Entity class. Let’s see an example of it:

package com.example.samplewebapp;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;

        name = "Person.findAllPersons",
        query =
            "SELECT * " +
            "FROM Person ", resultClass = Person.class

        name = "Person.findPersonByName",
        query =
            "SELECT * " +
            "FROM Person p " +
            "WHERE = ?", resultClass = Person.class)
public class Person {

    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;
    String name;
    String surname;

    // Getter and Setters omitted for brevity


In this example, we have defined two @NamedNativeQuery:

  • Person.findAllPersons: to return all Person Entities
  • Person.findPersonByName: to return all Person Entities filtered by name

Like JP QL named queries, the name of the query must be unique within the persistence unit. If the result type is an Entity, the resultClass element may be used to indicate the entity class. If the result requires a SQL mapping, you can use the SqlResultSetMapping element to specify the mapping name.


        name = "CustomerMapping",
        entities = @EntityResult(
                entityClass = Customer.class,
                fields = {
                    @FieldResult(name = "id", column = "id"),
                    @FieldResult(name = "firstName", column = "firstName"),
                    @FieldResult(name = "lastName", column = "lastName"),
                    @FieldResult(name = "address", column = "address")}))

Having defined the “CustomerMapping” as SqlResultSetMapping, you can now provide the name of the mapping instead of the entity class as a parameter to the createNativeQuery(String sqlString, String resultSetMapping) method:

List<Customer> results = this.em.createNativeQuery("SELECT as id, a.firstName, a.lastName, a.address FROM Customer c", "CustomerMapping").getResultList();

So it’s pretty obvious how to define a @NamedNativeQuery. Now let’s check how to run the @NamedNativeQuery. There are mainly two ways: using Spring Data Repository interface or the EntityManager interface.

Using Spring Data Repository interface

Spring Data JPA is able to bind automatically your NamedNativeQuery in your repository definition. Doing that is extremely simple if you follow Spring Data’s naming convention. The name of your query has to start with the name of your entity class, followed by “.” and the name of your repository method.

public interface PersonRepository extends CrudRepository<Person, Long> {

	 List<Person> findAllPersons(); 
	 List<Person> findPersonByName(String name);

When running the Main application class, we can reference our Repository interface and access data without the mediation of the EntityManager:

public class DemoApplication {
	private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

	public static void main(String[] args) {, args);
	public CommandLineRunner demo(PersonRepository repository) {
		return (args) -> {
			// save a couple of persons Person("Jack","Smith")); Person("Joe","Black")); Person("Martin","McFly"));

			// fetch all persons"Persons found with findAll():");"-------------------------------");
			for (Person person : repository.findAllPersons()) {;


			// fetch persons by last name"Person found with findByName('Jack'):");"--------------------------------------------");
			repository.findPersonByName("Jack").forEach(smith -> {;

Using the EntityManager to run the @NamedNativeQuery

Finally, if you are using the EntityManager interface to extract your data, then you can simply reference the @NamedNativeQuery from within the “createNamedQuery” as you can see in this example:

public class PersonController {
	EntityManager em;

    public List<Person> findAll() {
        Query q = em.createNamedQuery("Person.findAllPersons");      
        return q.getResultList();

    public List<Person> findOne(@PathVariable String name) {
        Query q = em.createNamedQuery("Person.findPersonByName");      
        q.setParameter(1, name);
        return q.getResultList();


You can test the above REST methods:

$ curl -s http://localhost:8080/findNames | jq
    "id": 1,
    "name": "Jack",
    "surname": "Smith"
    "id": 2,
    "name": "Joe",
    "surname": "Black"
    "id": 3,
    "name": "Martin",
    "surname": "McFly"

$ curl -s http://localhost:8080/findByName/Jack | jq
    "id": 1,
    "name": "Jack",
    "surname": "Smith"

We have just covered how to use the @NamedNativeQuery to execute native SQL statement from your Hibernate/JPA applications.