Spring und JDK 8: Verwenden Sie immer noch @Param und Name / Wert in Spring MVC-Anmerkungen? Dann ist der Artikel für Sie


Hallo, der Leser!


Während ich ein Schulungsprojekt für Spring Boot 2 entwickelte, entschied ich mich, mit @Param in Spring Data JPA-Abfragen zu experimentieren, oder besser gesagt, mit deren Abwesenheit :


 @Transactional(readOnly = true) public interface UserRepository extends JpaRepository<User, Integer> { @Query("SELECT u FROM User u WHERE LOWER(u.email) = LOWER(:email)") Optional<User> findByEmailIgnoreCase(@Param("email") String email); List<User> findByLastNameContainingIgnoreCase(@Param("lastname") String lastName); } 

(Über Magie, wie die zweite Methode funktioniert, steht in der alten Veröffentlichung " Following the Trail of Spring Pet Clinic" ).


@Param Entfernen von @Param Sie sicherstellen, dass Spring ohne sie @Param funktioniert . Ich habe von einem Parameter in der Kompilierung gehört, mit dem Sie Namen in Anmerkungen nicht duplizieren können, aber ich habe nichts Besonderes getan, also habe ich mich entschieden tiefer graben einen Deal machen.


Wenn Sie immer noch die Anmerkungen aus dem Titel des Artikels, Spring Boot und JDK 8, verwenden, frage ich nach Katze:


UPDATE: @PathVariable @RequestParam @PathVariable und @RequestParam werden häufig noch benötigt, damit die Anwendung ordnungsgemäß funktioniert. Ihre value/name Namensattribute sind jedoch nicht mehr erforderlich: Der Abgleich wird nach Variablennamen gesucht.


  • Als erstes habe ich versucht, den Namen im Parameter zu ändern ( mail statt email ):


     @Query("SELECT u FROM User u WHERE LOWER(u.email) = LOWER(:email)") Optional<User> findByEmailIgnoreCase(String mail); 

    Ich bekomme die Rezeption und den Platz für den Haltepunkt:


     Caused by: java.lang.IllegalStateException: Using named parameters for method public abstract java.util.Optional ru.javaops.bootjava.restaurantvoting.repository.UserRepository.findByEmailIgnoreCase(java.lang.String) but parameter 'Optional[mail]' not found in annotated query 'SELECT u FROM User u WHERE LOWER(u.email) = LOWER(:email)'! at org.springframework.data.jpa.repository.query.JpaQueryMethod.assertParameterNamesInAnnotatedQuery(JpaQueryMethod.java:125) ~[spring-data-jpa-2.1.3.RELEASE.jar:2.1.3.RELEASE] 

  • Als nächstes finden wir die Stelle, an der der Name des Methodenparameters bestimmt wird:




Es ist ersichtlich, dass zwei Strategien verwendet werden: StandardReflectionParameterNameDiscoverer und LocalVariableTableParameterNameDiscoverer . Der erste verwendet den JDK8 JEP 118: Zugriff auf Parameternamen zur Laufzeit . Laut SPR-9643 versucht Spring, die "ASM-basierte Debug-Symbol-Analyse" zu verwenden, wenn es nicht möglich ist, die Parameternamen gemäß der ersten Strategie zu bestimmen.


  • Es gibt viele Informationen zu den Java 8-Parameternamen im Internet. Eine Kompilierung mit dem Flag -parameters ist -parameters . Ich gehe zu den Spring Boot-Einstellungen des IDEA-Projekts:


Ja, es ist wirklich enthalten ... Aber was ist, wenn ich das Projekt über Maven erstelle und ausführe?
Das Ergebnis ist das gleiche!


  • Ich aktiviere die Debug-Ausgabe in den Maven-Einstellungen, kompiliere das Projekt und sehe:


     [DEBUG] Goal: org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) ... <parameters default-value="false">true</parameters> 

    Es sieht so aus, als ob das maven-compiler-plugin bereits in spring-boot-starter-parent konfiguriert ist, von wo spring-boot Projekte standardmäßig geerbt werden, wenn sie über SPRING INITIALIZR generiert werden. Wir gehen dorthin und ( nur für Spring Boot 2 ) sicher, dass das Plugin dort konfiguriert ist:


      <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <parameters>true</parameters> </configuration> </plugin> 

  • Schließlich können wir die Konfiguration des maven-compiler-plugin in unserem Projekt neu definieren, wobei wir dieses Flag auf false . Überprüfen Sie - das Projekt wurde gestartet. Und wenn wir versuchen, die Methode anzuwenden, erhalten wir:


     Unable to detect parameter names for query method ru.javaops.bootjava.restaurantvoting.repository.UserRepository.findByEmailIgnoreCase! Use @Param or compile with -parameters on JDK 8. 


Dies bedeutet, dass:


  1. Unsere Argumentation ist richtig
  2. Basierend auf der zweiten ASM-Strategie konnte ich die Informationen nicht erhalten (obwohl ich über Debug angefangen habe).

ERGEBNIS: Das Flag -parameters in Spring Boot 2 ist standardmäßig aktiviert. Wenn Sie also von spring-boot-starter-parent erben, werden die Parameternamen zur @Param definiert und @Param , @RequestParam , @PathVariable nicht mehr erforderlich. Weniger Code, weniger Fehler.


Für Spring Boot 1.x kann das Kompilierungsflag zwangsweise aktiviert werden (siehe oben).


PS: Ich habe JDK 8, JDK 11 und Spring Boot 2.1.1 für Forschungszwecke verwendet


UPDATE 2: Es ist interessant, dass für @RequestParam und @PathVariable zweite die zweite LocalVariableTableParameterNameDiscoverer Strategie basierend auf den von ASM aus dem Bytecode empfangenen Informationen LocalVariableTableParameterNameDiscoverer . Einschließlich für den regulären Frühling (ohne Boot) und ohne Kompilierungsoption.


Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de440214/


All Articles