Spring Boot 4 – komplett guide · Lektion

JPQL och nativa queries med @Query

Skriv explicita JPQL- och nativa SQL-queries, bind namngivna och positionella parametrar och mappa projektioner.

Lektion 2 av 413 steg

JPQL och nativa queries med @Query är en gratis lektion i Spring Boot 4 – komplett guide på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Spring Boot 4 – komplett guide, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.

Varför @Query finns

Spring Data JPA kan härleda frågor från metodnamn som findByLastName, men härledda frågor räcker inte till för sådant som inte är trivialt: joiner mellan entiteter, aggregeringar, anpassade projektioner eller finjusterad SQL.

Annoteringen @Query låter Er koppla en explicit fråga till en repository-metod. Ni skriver frågan en gång, deklarativt, och Spring binder metodens parametrar och mappar resultatet.

  • JPQL — ett objektorienterat frågespråk som arbetar mot entiteter och fält.
  • Native SQL — rå SQL för databasen när Ni behöver leverantörsspecifika funktioner eller handoptimerade frågor.

En grundläggande JPQL @Query

JPQL liknar SQL men arbetar med entitetsnamn och Java-fältnamn, inte tabell- och kolumnnamn. Här är User entitetsklassen och email ett Java-fält.

Observera platshållaren ?1 — detta är en positionsparameter som binds till det första metodargumentet.

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.email = ?1")
    Optional<User> findByEmailAddress(String email);
}

Namngivna parametrar med @Param

Positionsparametrar (?1, ?2) fungerar, men de blir problematiska när Ni ändrar argumentens ordning. Namngivna parametrar är tydligare och säkrare: skriv :name i frågan och bind den med @Param("name").

  • Strängen i @Param måste exakt motsvara :placeholder.
  • Metodargumentens ordning spelar inte längre någon roll.
public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.status = :status AND u.age >= :minAge")
    List<User> findActiveAdults(@Param("status") String status,
                               @Param("minAge") int minAge);
}

Namngivna eller positionella — vad ska man använda?

Båda stilarna binder metodargument till frågan, men de skiljer sig åt när det gäller underhåll.

  • Positionella (?1) — kortfattade för en eller två parametrar, men känsliga när Ni lägger till eller ordnar om argument.
  • Namngivna (:status) — självbeskrivande och tåliga vid refaktorering; föredras för frågor med flera parametrar.

Teamets standard i Spring Boot 4-projekt är att föredra namngivna parametrar för bättre läsbarhet. Använd positionella parametrar för mycket korta frågor.

Frågor med Native SQL

När Ni behöver databasspecifik SQL — fönsterfunktioner, leverantörstillägg eller en handoptimerad sats — anger Ni nativeQuery = true. Då körs frågan som rå SQL mot tabell- och kolumnnamn, inte entitetsfält.

Resultatet mappas fortfarande tillbaka till entiteten User, eftersom de valda kolumnerna motsvarar entitetens tabell.

public interface UserRepository extends JpaRepository<User, Long> {

    @Query(value = "SELECT * FROM users WHERE email = :email",
           nativeQuery = true)
    Optional<User> findByEmailNative(@Param("email") String email);
}

JPQL eller Native — välj rätt verktyg

Utgå från JPQL och använd endast native SQL när JPQL inte kan uttrycka det Ni behöver.

  • JPQL — portabelt mellan databaser, säkert vid refaktorering (använder Java-fältnamn) och integrerat med persistence context.
  • Native — full SQL-kraft och leverantörsfunktioner, men binder Er till en viss databassyntax och kringgår vissa av JPA:s bekvämligheter.

En vanlig fallgrop är att jokertecken med LIKE och paginering i native-frågor måste följa databasens SQL, inte JPQL-reglerna.

Gränssnittsbaserade projektioner

Ofta behöver Ni inte hela entiteten — bara några kolumner. En projektion returnerar en lättviktsvy i stället för en fullständig User.

Definiera ett gränssnitt med getters; Spring matchar varje getter mot ett valt alias. Då läses endast de kolumner som Ni efterfrågar in.

public interface UserSummary {
    String getName();
    String getEmail();
}

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u.name AS name, u.email AS email FROM User u WHERE u.active = true")
    List<UserSummary> findActiveSummaries();
}

Alias är viktiga för projektioner

För att en gränssnittsprojektion ska bindas måste varje valt uttryck ha ett alias som motsvarar getter-namnet. Gettern getEmail() mappas till aliaset email.

  • SELECT u.email AS email binds till getEmail().
  • Om aliaset utelämnas för en beräknad kolumn förblir gettern omappad och returnerar null.

Detta gäller både JPQL- och native-projektionsfrågor.

DTO-projektioner med konstruktoruttryck

JPQL stöder även konstruktoruttryck: bygg en DTO direkt i frågan med nyckelordet NEW. Du måste använda det fullständigt kvalificerade klassnamnet och matcha ordningen på konstruktorns parametrar.

Det ger dig ett oföränderligt, typat resultatsobjekt i stället för en gränssnittsproxy.

public record UserDto(String name, String email) {}

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT new com.example.app.UserDto(u.name, u.email) FROM User u WHERE u.active = true")
    List<UserDto> findActiveDtos();
}

Ändringsfrågor

@Query kan även köra UPDATE- och DELETE-satser. Dessa kräver @Modifying så att Spring kör dem som uppdateringar i stället för urval, och de körs vanligtvis i en @Transactional-metod.

Returvärdet är antalet påverkade rader.

public interface UserRepository extends JpaRepository<User, Long> {

    @Modifying
    @Transactional
    @Query("UPDATE User u SET u.status = :status WHERE u.lastLogin < :cutoff")
    int deactivateStale(@Param("status") String status,
                        @Param("cutoff") LocalDate cutoff);
}

En fristående mental modell för JPQL

Parameterbindning i JPQL motsvarar hur du själv skulle ersätta värden. Kodavsnittet nedan är ren Java som demonstrerar idén med ersättning av namngivna parametrar bakom :status och :minAge — ingen databas krävs.

I verklig kod utför Spring denna bindning säkert via förberedda satser; detta illustrerar endast konceptet.

import java.util.Map;

public class ParamBindingDemo {
    static String bind(String query, Map<String, String> params) {
        for (Map.Entry<String, String> e : params.entrySet()) {
            query = query.replace(":" + e.getKey(), e.getValue());
        }
        return query;
    }

    public static void main(String[] args) {
        String jpql = "SELECT u FROM User u WHERE u.status = :status AND u.age >= :minAge";
        Map<String, String> params = Map.of("status", "'ACTIVE'", "minAge", "18");
        System.out.println(bind(jpql, params));
    }
}

Snabb kontroll

Testa din förståelse av parameterbindning och projektioner med @Query.

Sammanfattning

Du vet nu hur du skriver explicita frågor med @Query:

  • JPQL arbetar med entitets- och fältnamn; inbyggd SQL (nativeQuery = true) arbetar med tabeller och kolumner.
  • Bind värden med positionsbaserade (?1) eller, helst, namngivna (:name + @Param) parametrar.
  • Gränssnittsprojektioner kräver alias som matchar getter-namnen; konstruktoruttryck (SELECT new ...) bygger typade DTO:er.
  • Använd @Modifying (med @Transactional) för UPDATE-/DELETE-frågor.

Använd som standard JPQL för portabilitet och välj inbyggd SQL endast när du verkligen behöver databasspecifik funktionalitet.

Gratis att börja

Lär dig Java med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
21
Lektioner
84

Vanliga frågor

Är lektionen ”JPQL och nativa queries med @Query” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Spring Boot 4 – komplett guide, inklusive ”JPQL och nativa queries med @Query”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.

Vad lär jag mig i ”JPQL och nativa queries med @Query”?

Skriv explicita JPQL- och nativa SQL-queries, bind namngivna och positionella parametrar och mappa projektioner. Ni övar på Spring Boot 4 – komplett guide med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Spring Boot 4 – komplett guide?

Du behöver inga förkunskaper. Utbildningen i Spring Boot 4 – komplett guide på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”JPQL och nativa queries med @Query”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Spring Boot 4 – komplett guide-lektionen?

Ja. Varje Spring Boot 4 – komplett guide-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Härledda query-metoder och nyckelordsupplösning
  2. JPQL och nativa queries med @Query
  3. Specifications och kriteriebaserad dynamisk filtrering
  4. Paginering, sortering och strömning av sidor
← Tillbaka till Spring Boot 4 – komplett guide