
Bonjour, le lecteur!
En développant un projet de formation sur Spring Boot 2, j'ai décidé d'expérimenter @Param
dans les requêtes Spring Data JPA, ou plutôt, avec leur absence :
@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); }
(sur la magie, le fonctionnement de la deuxième méthode se trouve dans l'ancienne publication Follow the Trail of Spring Pet Clinic ).
@Param
supprimant @Param
vous pouvez vous assurer que Spring fonctionne très bien sans eux . J'ai entendu parler d'un paramètre de compilation qui vous permet de ne pas dupliquer les noms dans les annotations, mais je n'ai rien fait de spécial, j'ai donc décidé creuser plus profondément faire un marché.
Si vous utilisez toujours les annotations du titre de l'article, Spring Boot et JDK 8, je demande cat:
MISE À JOUR: les @RequestParam
@PathVariable
et @RequestParam
sont encore souvent nécessaires pour que l'application fonctionne correctement. Mais leurs attributs value/name
ne sont plus nécessaires: la correspondance est recherchée par les noms de variables.
La première chose que j'ai essayée a été de changer le nom dans le paramètre ( mail
au lieu d' email
):
@Query("SELECT u FROM User u WHERE LOWER(u.email) = LOWER(:email)") Optional<User> findByEmailIgnoreCase(String mail);
J'obtiens l'accueil et la place pour le point d'arrêt:
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]
Ensuite, nous trouvons l'endroit où le nom du paramètre de méthode est déterminé:

On peut voir que 2 stratégies sont utilisées: StandardReflectionParameterNameDiscoverer
et LocalVariableTableParameterNameDiscoverer
. Le premier utilise le JDK8 JEP 118: Accès aux noms de paramètres au moment de l'exécution . Selon SPR-9643 , s'il n'est pas possible de déterminer les noms de paramètres par la première stratégie, Spring essaie d'utiliser "l'analyse des symboles de débogage basée sur ASM".
- Il y a beaucoup d'informations sur les noms des paramètres Java 8 sur Internet, une compilation avec l'indicateur
-parameters
est -parameters
. Je vais dans les paramètres Spring Boot du projet IDEA:

Oui, c'est vraiment inclus ... Mais que se passe-t-il si je crée et exécute le projet via Maven?
Le résultat est le même!
J'active la sortie de débogage dans les paramètres Maven, compile le projet et vois:
[DEBUG] Goal: org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) ... <parameters default-value="false">true</parameters>
Il semble que le maven-compiler-plugin
déjà configuré dans spring-boot-starter-parent
, d'où spring-boot
projets spring-boot
sont hérités par défaut lorsqu'ils sont générés via SPRING INITIALIZR . On y va et ( uniquement pour Spring Boot 2 ) c'est sûr, le plugin y est configuré:
<plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <parameters>true</parameters> </configuration> </plugin>
Enfin, nous pouvons redéfinir la configuration maven-compiler-plugin
dans notre projet, où nous définissons ce drapeau sur false
. Vérifiez - le projet a commencé. Et en essayant de tirer la méthode, nous obtenons:
Unable to detect parameter names for query method ru.javaops.bootjava.restaurantvoting.repository.UserRepository.findByEmailIgnoreCase! Use @Param or compile with -parameters on JDK 8.
Cela signifie que:
- notre raisonnement est correct
- Sur la base de la deuxième stratégie ASM, je n'ai pas pu obtenir les informations (même si j'ai commencé par Debug)
RÉSULTAT: l'indicateur -parameters
dans Spring Boot 2 est activé par défaut, donc si vous héritez de spring-boot-starter-parent
, les noms des paramètres sont définis dans le @Param
et @Param
, @RequestParam
, @PathVariable
ne @PathVariable
plus requis. Moins de code, moins d'erreurs.
Pour Spring Boot 1.x, l'indicateur de compilation peut être activé de force, voir ci-dessus.
PS: j'ai utilisé JDK 8, JDK 11 et Spring Boot 2.1.1 pour la recherche
MISE À JOUR 2: il est intéressant de noter que pour @RequestParam
et @PathVariable
seconde fonctionne avec la deuxième stratégie LocalVariableTableParameterNameDiscoverer
basée sur les informations reçues par ASM du bytecode. Y compris pour Spring ordinaire (sans Boot) et sans option de compilation.
Merci de votre attention!