@Query-Annotation in Spring Data JPA

In meinem vorherigen Beitrag zu Spring Data habe ich die grundlegenden Konzepte und Konfigurationen für Spring Data JPA erläutert. In diesem Tutorial werde ich es erklären @Query Annotation und wie man eine benutzerdefinierte Abfrage mit der erstellt @Query Anmerkung.

Der größte Vorteil der Verwendung von Spring Data besteht darin, dass die Repositorys zur Laufzeit zum Erstellen der Abfragen implementiert werden. Entwickler müssen sich keine Gedanken über SQL-Kenntnisse und das Schreiben fehleranfälliger SQL-Abfragen machen. Zur Erstellung der dynamischen Abfragen werden in Spring-Datenrepositorys implementierte Abfragemethoden verwendet.

Wenn Sie jedoch sehr komplexe Abfragen mit mehreren Bedingungen zum Filtern der Daten schreiben möchten, wäre der Name der Abfragemethode schrecklich. Um diese Situation zu vermeiden, kann man bequem die JPQL/SQL-Abfragen innerhalb des verwenden @Query Anmerkung. Diese Annotation unterstützt sowohl JPA Query Language (JPQL) als auch SQL. Ich werde erklären, wie man Abfragen mithilfe von Abfrageannotationen in Spring Data JPA schreibt.

@Query-Annotation in Spring Data JPA

Wenn Sie auf Probleme stoßen, schreiben Sie es bitte in den Kommentarbereich oder wenden Sie sich direkt an mich, um Hilfe zu erhalten.

Hier ist die Liste der Themen, die in diesem Tutorial behandelt werden.

  • @Query-Anmerkung
  • Wie Ausdrücke
  • So verwenden Sie native SQL-Abfragen
  • Benannte Parameter mit @Param
  • SpEL-Ausdrücke
  • Beispielanwendung
  • Quellcode
  • Abschluss
  • @Query-Anmerkung

    • Wenn Sie die Abfragemethoden nicht zum Ausführen von Datenbankoperationen verwenden können, @Query könnte verwendet werden, um die flexiblere Abfrage zum Abrufen von Daten zu schreiben.
    • @Query Annotation unterstützt sowohl JPQL- als auch native SQL-Abfragen.
    • Standardmäßig, @Query Annotation verwendet JPQL, um die Abfragen auszuführen. Wenn Sie versuchen, die normalen SQL-Abfragen zu verwenden, erhalten Sie Ausnahmen bezüglich der Abfragesyntaxfehler.
    • Wenn Sie native SQL-Abfragen schreiben möchten, legen Sie fest nativeQuery Flagge zu true. Auch Paginierung und dynamische Sortierung für native Abfragen werden in Spring Data JPA nicht unterstützt.
    • Wenn Sie die Abfragemethoden mit verwenden @Query Anmerkung, diese hat Vorrang @NamedQuerybenannte Abfragen in orm.xml und Methodennamen.
    • Wenn wir beispielsweise eine Abfragemethode namens findByName() erstellen und sie mit dem kommentieren @Query Anmerkung: Spring Data JPA findet nicht, dass die Entität mit der Namenseigenschaft gleich dem angegebenen Methodenparameter ist. Es würde die Abfrage aufrufen, die mithilfe von konfiguriert wird @Query Anmerkung.

    Ein einfacher Beispielausschnitt für die Verwendung der Abfrageanmerkung.

    @Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
    List<Book> findByPriceRange(long price1, long price2);
    

    Es handelt sich um ein einfaches Beispiel für die Abfrageanmerkung. Im obigen Snippet benötigen wir Parameter, um die Preise zu vergleichen und die Ergebnisse zu filtern. Vor dem Parameter in der Abfrage steht ? Zeichen, um anzugeben, dass dies der Parameter ist, der mit Methodenargumenten verknüpft werden soll.

    Wie Ausdrücke

    Man kann den erweiterten Like-Mechanismus im Inneren verwenden @Query Definition. Das Beispiel für die Verwendung der Like-Ausdrücke in der Abfrage ist wie folgt:

    @Query(value = "select name,author,price from Book b where b.name like %:name%")
    List<Book> findByNameMatch(@Param("name") String name);
    

    In der obigen Abfrage verwenden wir den Like-Ausdruck, um die Ergebnisse zu filtern.

    So verwenden Sie native SQL-Abfragen

    Wie ich im vorherigen Abschnitt hervorgehoben habe, unterstützt die Abfrageannotation die Definition einer nativen SQL-Abfrage durch die Aktivierung von nativeQuery Flag in der Abfrageanmerkung. Diese Funktion ist sehr praktisch, wenn Sie anstelle der JPQL-Syntax nur die normale Datenbankabfragesyntax ausprobieren möchten.

    Hier ist der Beispielcode für die Verwendung der nativen SQL-Abfrage in @Query Anmerkung:

    @Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
    List<Book> findByName(String name);
    

    Im obigen Beispiel-Codeausschnitt verwenden wir die nativeQuery=true um Spring Data JPA anzuweisen, die native Abfrageausführung zu verwenden. Standardmäßig ist der Wert für dieses Flag false.

    Benannte Parameter mit @Param

    • Standardmäßig werden Spring Data-Abfrageparameter basierend auf ihrer Position ersetzt. Dies ist fehleranfällig, wenn Sie den Code umgestalten und die Parameterpositionen aktualisieren.
    • @Param Annotation kann im Methodenparameter verwendet werden, um die Namen der Abfrageparameter zu binden.
    • Innerhalb der Abfrage müssen Sie verwenden :paramName um darauf hinzuweisen, dass das Gleiche der Fall ist paramName muss mit dem Methodenparameter gebunden werden.

    Hier ist der Beispielcode:

    @Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
    List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
    		@Param("price") long price);
    

    In der obigen Abfrage verwenden wir die benannten Parameter, um die Abfrageparameter und Methodenargumente zu binden. Dies ist die am meisten empfohlene Methode zum Binden der Parameter. Wenn wir mehrere Parameter haben, ist diese Option anstelle einer positionsbasierten Bindung sinnvoll.

    SpEL-Ausdrücke

    Die Unterstützung für den SpEL-Ausdruck in der Abfrage ist begrenzt und wird ab der Version Spring Data JPA 1.4 eingeführt. Wenn die Abfrage ausgeführt wird, wird die Abfrage mithilfe der SpEL-Ausdrücke mit dem vorab festgelegten Wert ausgewertet.
    Hier ist der Beispielcode für SpEL-Ausdrücke.

    @Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
    List<Book> findByName(String name);
    

    #{#entityName} ist der SpEL-Ausdruck, der zum Abrufen des Entitätsnamens verwendet wird. Derzeit werden SpEL-Ausdrücke nur für den Entitätsnamen verwendet. In der zukünftigen Version könnte es weitere Ausdrücke geben.

    @Query-Annotation-Beispielanwendung

    Beachten Sie, dass ich hier nicht den gesamten Code aufführe, der für dieses Tutorial verwendet wird. Wenn Sie das gesamte Projekt durchsuchen möchten, laden Sie bitte den Quellcode im Download-Bereich herunter.

    Die einzige zusätzliche Klasse, die ich für dieses Beispiel hinzugefügt habe, ist eine neue Repository-Schnittstelle zum Definieren der Abfragemethoden @Query Anmerkung.

    BookQueryRepositoryExample.java

    Hier ist die neue Repository-Klasse zur Demonstration @Query Anmerkung.

    public interface BookQueryRepositoryExample extends Repository<Book, Long> {
    	@Query(value = "select * from Book b where b.name=?1", nativeQuery = true)
    	List<Book> findByName(String name);
    
    	@Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
    	List<Book> findByPriceRange(long price1, long price2);
    
    	@Query(value = "select name,author,price from Book b where b.name like %:name%")
    	List<Book> findByNameMatch(@Param("name") String name);
    
    	@Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
    	List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
    			@Param("price") long price);
    
    }
    

    Abgesehen von der oben genannten Klasse habe ich die Controller-Klasse geändert. Die Dienstimplementierung greift über die REST-API auf dieses Repository zu.

    Auch ich habe neu hinzugefügt data.sql Und schema.sql um die Daten zum Zeitpunkt des Starts der Spring Boot-Anwendung zu initialisieren.

    data.sql

    INSERT INTO book(id,name,author,price) VALUES (1,'Spring In Action:Covers Spring 3.0','Craig Walls', 400);
    INSERT INTO book(id,name,author,price) VALUES (2,'Spring Batch In Action','Arnaud Cogoluegnes', 500);
    INSERT INTO book(id,name,author,price) VALUES (3,'Spring Book','Rod', 300);
    INSERT INTO book(id,name,author,price) VALUES (4,'Java Book','test', 100);
    INSERT INTO book(id,name,author,price) VALUES (5,'Spring Boot Application','test', 200);
    INSERT INTO book(id,name,author,price) VALUES (6,'Learn Spring Data JPA','test', 300);
    INSERT INTO book(id,name,author,price) VALUES (7,'Hibernat in Action','Gavin King', 300);
    INSERT INTO book(id,name,author,price) VALUES (8,'JSF in Action','Kit', 400);
    INSERT INTO book(id,name,author,price) VALUES (9,'Java Interview Questions','Subramanian', 450);
    INSERT INTO book(id,name,author,price) VALUES (10,'Java Complete Reference','Herbert', 450);
    

    schema.sql

    create table book(
          id int not null primary key,
          name varchar_ignorecase(50) not null,
          author varchar_ignorecase(50) not null,
          price int);
    
    

    Laden Sie den Quellcode herunter

    Hier steht der vollständige Quellcode für dieses Tutorial zum Download bereit. Dieser Quellcode ist nicht nur für das Abfrageanmerkungsbeispiel gedacht, sondern enthält auch alle anderen Spring Data JPA-Beispiele.

    Symbol

    Spring Data JPA mit Spring Boot-Beispielanwendung

    1 Datei(en) 12,43 KB Download: Spring Data JPA mit Spring Boot

    Abschluss

    Ich hoffe, dass dieses Tutorial mehr Einblick in die Verwendung der Abfrageanmerkung gegeben hat. Wenn Sie mit Spring Data arbeiten, ist es wichtig, die Funktionen der Abfrageannotation zu verstehen, da die Verwendung von Abfragemethoden in den meisten Fällen nicht ausreicht. In diesem Tutorial habe ich die Verwendung erklärt @Query Annotation in den Abfragemethoden, Verwendung ähnlicher Ausdrücke, Verwendung benannter Parameter für die Bindung und SpEL-Ausdruck innerhalb der Abfrage. Wenn Sie daran interessiert sind, die Grundlagen von Spring Data JPA zu lesen, lesen Sie bitte unser ausführlicheres Tutorial zu Spring Data JPA.

    Ausnahmen

    QuerySyntaxException: Unerwartetes Token/Validierung für die Abfrage der Methode fehlgeschlagen

    Wenn Sie versuchen, native SQL-Abfragen auszuführen, kann die folgende Ausnahme auftreten. Wenn die folgende Ausnahme auftritt, besteht höchstwahrscheinlich die Möglichkeit, dass Sie eine native SQL-Abfrage ohne das Attribut verwenden nativeQuery=true. Wenn Sie die SQL-Abfrage ohne das Attribut verwenden nativeQuery=true, Spring Data JPA wird versuchen, die Abfrage anhand des JPQL-Formats zu validieren. Sie erhalten die folgende Ausnahme.

    Beachten Sie, dass dieselbe Ausnahme auch dann ausgelöst wird, wenn in der Abfrage ein Syntaxfehler vorliegt.

    Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List net.javabeat.spring.data.service.BookQueryRepositoryExample.findByName(java.lang.String)!
    	at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:92)
    	at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62)
    Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: * near line 1, column 8 [select * from net.javabeat.spring.data.domain.Book b where b.name=?1]
    	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750)
    	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
    

    Um die oben genannte Ausnahme zu vermeiden, fügen Sie das nativeQuery-Attribut wie folgt hinzu:

    @Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
    List<Book> findByName(String name);
    

    Wenn dieses Tutorial nützlich ist, freuen wir uns. Wenn Sie die Informationen finden, nach denen Sie suchen, bitten Sie uns bitte im Kommentarbereich, das Tutorial zu aktualisieren.

    Kommentar verfassen

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

    Nach oben scrollen