Spring و JDK 8: هل ما زلت تستخدمParam والاسم / القيمة في التعليقات التوضيحية Spring MVC؟ ثم المقالة لك


مرحبا ، القارئ!


أثناء تطوير مشروع تدريبي على برنامج Spring Boot 2 ، قررت تجربة @Param في استعلامات Spring Data JPA ، أو بالأحرى مع غيابها :


 @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); } 

(عن السحر ، كيف تعمل الطريقة الثانية في المنشور القديم التالي لـ Trail of Spring Pet Clinic ).


@Param إزالة @Param يمكنك التأكد من أن Spring يعمل بشكل جيد بدونها . سمعت بمعلمة في التجميع تتيح لك عدم تكرار الأسماء في التعليقات التوضيحية ، لكنني لم أفعل أي شيء خاص ، لذلك قررت حفر أعمق عقد صفقة.


إذا كنت لا تزال تستخدم التعليقات التوضيحية من عنوان المقال ، Spring Boot و JDK 8 ، فأنا أطلب cat:


استكمال: لا تزال هناك حاجة إلى @RequestParam و @RequestParam حتى يعمل التطبيق بشكل صحيح. لكن سمات value/name لم تعد مطلوبة: يتم البحث عن مطابقة بواسطة أسماء المتغيرات.


  • أول شيء حاولت تغيير الاسم في المعلمة ( mail بدلاً من email ):


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

    أحصل على مكان الاستقبال ونقطة التوقف:


     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] 

  • بعد ذلك ، نجد المكان الذي يتم فيه تحديد اسم معلمة الطريقة:




يمكن ملاحظة أنه يتم استخدام استراتيجيات 2: StandardReflectionParameterNameDiscoverer و LocalVariableTableParameterNameDiscoverer . الأول يستخدم JDK8 JEP 118: الوصول إلى أسماء المعلمات في وقت التشغيل . وفقًا لـ SPR-9643 ، إذا لم يكن من الممكن تحديد أسماء المعلمات عن طريق الاستراتيجية الأولى ، يحاول Spring استخدام "تحليل رمز تصحيح الأخطاء المستند إلى ASM".


  • هناك الكثير من المعلومات حول Java 8 Parameter Names على الإنترنت ، -parameters التجميع باستخدام علامة -parameters . أذهب إلى إعدادات Spring Boot في مشروع IDEA:


نعم ، لقد تم تضمينه بالفعل ... ولكن ماذا لو قمت ببناء وتشغيل المشروع من خلال Maven؟
والنتيجة هي نفسها!


  • أقوم بتشغيل إخراج تصحيح في إعدادات Maven ، ترجمة المشروع ونرى:


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

    يبدو أن maven-compiler-plugin تم تهيئته بالفعل في spring-boot-starter-parent spring-boot ، حيث يتم توريث مشاريع spring-boot افتراضيًا عند إنشائها عبر SPRING INITIALIZR . نذهب إلى هناك و ( فقط من أجل Spring Boot 2 ) بالتأكيد ، تم تكوين المكون الإضافي هناك:


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

  • أخيرًا ، يمكننا إعادة تعريف تكوين maven-compiler-plugin في مشروعنا ، حيث نضع هذه العلامة على false . تحقق - بدأ المشروع. وعند محاولة سحب الطريقة نحصل على:


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


هذا يعني أن:


  1. منطقنا صحيح
  2. استنادًا إلى استراتيجية ASM الثانية ، لم أستطع الحصول على المعلومات (على الرغم من أنني بدأت من خلال Debug)

RESULT: يتم -parameters علامة -parameters في Spring Boot 2 افتراضيًا ، لذلك إذا كنت ترث من spring-boot-starter-parent ، فسيتم تحديد أسماء المعلمات في @Param و @Param ، @RequestParam ، @PathVariable لم تعد مطلوبة. رمز أقل ، أخطاء أقل.


بالنسبة لـ Spring Boot 1.x ، يمكن تمكين علامة الترجمة بالقوة ، انظر أعلاه.


ملاحظة: استخدمت JDK 8 ، JDK 11 ، و Spring Boot 2.1.1 للبحث


UPDATE 2: من المثير أنه بالنسبة إلى @RequestParam و @PathVariable تعمل الثانية الثانية لاستراتيجية LocalVariableTableParameterNameDiscoverer الثانية بناءً على المعلومات التي تلقاها ASM من LocalVariableTableParameterNameDiscoverer البريدي. بما في ذلك الربيع العادية (بدون التمهيد) وبدون خيار التحويل البرمجي.


شكرا لاهتمامكم!

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


All Articles