Spring Data Jpa Query

Spring Data Jpa supports named queries to declare queries for Repository methods. Named Queries works fine for a small number of queries but with more complex queries Named Queries is not a good approach. Named Queries bind the actual executing queries to the domain object which will be called by the Repository method, in this scenario Repository method is tightly coupled with Domain object which is also not desired behaviour.

Spring Data Jpa provides a way to declare the queries directly on the Resposityr method suing @Query annotation. @Query decouple the dependency of Domain Object on Repository and remove persistence information from domain class to the repository interface.

Queries annotated to the query method take precedence over queries defined using @NamedQuery or named queries declared in orm.xml.

drop database if exists AppleDb;
create database AppleDb;
use AppleDb;
CREATE TABLE apple ( apple_id BIGINT NOT NULL, apple_name VARCHAR(255) DEFAULT NULL, taste VARCHAR(255) DEFAULT NULL, PRIMARY KEY (apple_id)) ENGINE=INNODB;
CREATE TABLE hibernate_sequence ( next_val BIGINT) ENGINE=INNODB;
insert into hibernate_sequence values ( 1 );
insert into apple (apple_name, apple_id, taste) values ("Macintosh", 1, "tangy");
insert into apple (apple_name, apple_id, taste) values ("Fuji", 2, "sweet");
insert into apple (apple_name, apple_id, taste) values ("Gala", 3, "juicy");
insert into apple (apple_name, apple_id, taste) values ("Jonagold", 4, "sweet");
insert into apple (apple_name, apple_id, taste) values ("GrannySmith", 5, "sharp");
package com.sujan.example.jpa.controller;

import com.sujan.example.jpa.entity.Apple;
import com.sujan.example.jpa.repository.AppleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class AppleController {
    @Autowired
    private AppleRepository appleRepository;

    @GetMapping
    void Query() {
        Apple findByAppleName = appleRepository.findByAppleName("Macintosh");
        System.out.println("findByAppleName = " + findByAppleName);
        List<Apple> appleList = appleRepository.findByTaste("sweet");
        appleList.forEach(System.out::println);
    }
}
package com.sujan.example.jpa.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

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

@Data
@Entity
@ToString
@NoArgsConstructor
@AllArgsConstructor()
public class Apple {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long appleId;
    private String appleName;
    private String taste;
}
package com.sujan.example.jpa.repository;

import com.sujan.example.jpa.entity.Apple;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface AppleRepository extends JpaRepository<Apple, Long> {
    @Query("select a from Apple a where a.appleName = ?1")
    Apple findByAppleName(String appleName);

    @Query("select a from Apple a where a.taste = ?1")
    List<Apple> findByTaste(String taste);
}
package com.sujan.example.jpa;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JpaApplication {
    public static void main(String[] args) {
        SpringApplication.run(JpaApplication.class, args);
    }
}
spring.datasource.url=jdbc:mysql://localhost:3306/AppleDb
spring.datasource.username=root
spring.datasource.password=root
plugins {
    id 'org.springframework.boot' version '2.3.3.RELEASE'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}
group = 'com.sujan'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}
repositories {
    mavenCentral()
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    annotationProcessor 'org.projectlombok:lombok'
    compileOnly 'org.projectlombok:lombok'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'mysql:mysql-connector-java'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}
test {
    useJUnitPlatform()
}
curl --location --request GET 'http://localhost:8080/'
select apple0_.apple_id as apple_id1_0_, apple0_.apple_name as apple_na2_0_, apple0_.taste as taste3_0_ from apple apple0_ where apple0_.apple_name=?
findByAppleName = Apple(appleId=1, appleName=Macintosh, taste=tangy)
select apple0_.apple_id as apple_id1_0_, apple0_.apple_name as apple_na2_0_, apple0_.taste as taste3_0_ from apple apple0_ where apple0_.taste=?
Apple(appleId=2, appleName=Fuji, taste=sweet)
Apple(appleId=4, appleName=Jonagold, taste=sweet)

follow us on