JPQL och nativa queries med @Query
Skriv explicita JPQL- och nativa SQL-queries, bind namngivna och positionella parametrar och mappa projektioner.
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
@Parammå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 emailbinds tillgetEmail().- 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örUPDATE-/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.
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
- Härledda query-metoder och nyckelordsupplösning
- JPQL och nativa queries med @Query
- Specifications och kriteriebaserad dynamisk filtrering
- Paginering, sortering och strömning av sidor