שפת שאילתת REST עם קריטריוני אביב ו- JPA
רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:
>> בדוק את הקורס מאמר זה הוא חלק מסדרה: • שפת שאילתת REST עם קריטריוני אביב ו- JPA (מאמר נוכחי) • שפת שאילתת REST עם מפרטי JPA של נתוני אביב• שפת שאילתת REST עם JPA ו- Querydsl Data Data
• שפת שאילתת REST - פעולות חיפוש מתקדמות
• שפת שאילתת REST - יישום או פעולה
• שפת שאילתת מנוחה עם RSQL
• שפת שאילתת מנוחה עם תמיכה ברשת Querydsl
1. סקירה כללית
במאמר ראשון זה בסדרה חדשה זו, נחקור שפת שאילתות פשוטה עבור REST API. אנו נשתמש היטב באביב עבור REST API ו- JPA 2 קריטריונים להיבטי ההתמדה.
מדוע שפת שאילתות? כי - לכל ממשק API מורכב מספיק - חיפוש / סינון המשאבים שלך לפי שדות פשוטים מאוד פשוט לא מספיק. שפת שאילתות גמישה יותר, ומאפשרת לך לסנן בדיוק את המשאבים שאתה צריך.
2. מִשׁתַמֵשׁ יֵשׁוּת
ראשית - בואו נציג את היישות הפשוטה בה אנו משתמשים עבור ה- API שלנו לסינון / חיפוש - בסיסי מִשׁתַמֵשׁ:
משתמש בכיתה ציבורית @Entity {@Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) פרטי מזהה ארוך; פרטי מחרוזת firstName; שם משפחה פרטי מחרוזת; דוא"ל מחרוזת פרטי; גיל פרטי פרטי; }
3. סינון באמצעות CriteriaBuilder
עכשיו - בואו ניכנס לבשר הבעיה - השאילתה בשכבת ההתמדה.
בניית הפשטה של שאילתות היא עניין של איזון. אנחנו זקוקים לכמות טובה של גמישות מצד אחד, ואנחנו צריכים לשמור על ניהול מורכבות מצד שני. ברמה גבוהה, הפונקציונליות היא פשוטה - אתה עובר כמה אילוצים ואתה מקבל בחזרה כמה תוצאות.
בואו נראה איך זה עובד:
מחסן ציבורי @ מאגר UserDAO מיישם את IUserDAO {@PersistenceContext EntityManager entityManager פרטי; @Override רשימות ציבוריות SearchUser (רשימת פאראמים) {CriteriaBuilder builder = entityManager.getCriteriaBuilder (); שאילתת CriteriaQuery = builder.createQuery (User.class); שורש r = query.from (User.class); חזוי פרדיקט = builder.conjunction (); UserSearchQueryCriteriaConsumer searchConsumer = UserSearchQueryCriteriaConsumer חדש (פרדיקט, בונה, r); params.stream (). forEach (searchConsumer); predicate = searchConsumer.getPredicate (); query.where (predicate); תוצאת רשימה = entityManager.createQuery (שאילתה) .getResultList (); תוצאת החזרה; } @ עקוף שמירה על ריק ריק (ישות משתמש) {entityManager.persist (ישות); }}
בואו נסתכל על ה- UserSearchQueryCriteriaConsumer מעמד:
מחלקה ציבורית UserSearchQueryCriteriaConsumer מיישם את הצרכן {פרדיקט פרדיקט; בונה פרטי CriteriaBuilder; שורש פרטי r; @ קביעת חלל ציבורי בטל (SearchCriteria param) {if (param.getOperation (). EqualsIgnoreCase (">")) {predicate = builder.and (predicate, builder .greaterThanOrEqualTo (r.get (param.getKey ()), param .getValue (). toString ())); } אחרת אם (param.getOperation (). equalsIgnoreCase ("<")) {predicate = builder.and (predicate, builder.lessThanOrEqualTo (r.get (param.getKey ()), param.getValue (). toString () )); } אחר אם (param.getOperation (). equalsIgnoreCase (":")) {if (r.get (param.getKey ()). getJavaType () == String.class) {predicate = builder.and (predicate, builder .like (r.get (param.getKey ()), "%" + param.getValue () + "%")); } אחר {predicate = builder.and (predicate, builder.equal (r.get (param.getKey ()), param.getValue ())); }}} // קונסטרוקטור סטנדרטי, גטר, סטר}
כפי שאתה יכול לראות, חיפוש משתמש API לוקח רשימה של אילוצים פשוטים מאוד, מרכיב שאילתה על סמך אילוצים אלה, מבצע חיפוש ומחזיר את התוצאות.
מעמד האילוצים פשוט למדי:
מחלקה ציבורית SearchCriteria {מפתח מחרוזת פרטי; פעולת מחרוזת פרטית; ערך אובייקט פרטי; }
ה SearchCriteria היישום מחזיק את שלנו שאילתא פרמטרים:
- מַפְתֵחַ: משמש להחזקת שם שדה - לדוגמא: שם פרטי, גיל, … וכו.
- מבצע: משמש לקיום הפעולה - לדוגמא: שוויון, פחות מ, ... וכו '.
- ערך: משמש להחזקת ערך השדה - לדוגמא: john, 25, ... וכו '.
4. בדוק את שאילתות החיפוש
עכשיו - בואו נבדוק את מנגנון החיפוש שלנו כדי לוודא שהוא מחזיק מים.
ראשית - בוא נתחיל את מסד הנתונים שלנו לבדיקה על ידי הוספת שני משתמשים - כמו בדוגמה הבאה:
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfig.class}) @ Transactional @ TransactionConfiguration public class JPACriteriaQueryTest {@Autowired פרטי IUserDAO userApi; משתמש פרטי משתמש ג'ון; UserTom פרטי; @ לפני init בטל פומבי () {userJohn = משתמש חדש (); userJohn.setFirstName ("ג'ון"); userJohn.setLastName ("איילה"); userJohn.setEmail ("[דוא"ל מוגן]"); userJohn.setAge (22); userApi.save (userJohn); userTom = משתמש חדש (); userTom.setFirstName ("טום"); userTom.setLastName ("איילה"); userTom.setEmail ("[דוא"ל מוגן]"); userTom.setAge (26); userApi.save (userTom); }}
עכשיו, בואו נקבל מִשׁתַמֵשׁ עם ספציפי שם פרטי ו שם משפחה - כמו בדוגמה הבאה:
@Test הציבור בטל givenFirstAndLastName_whenGettingListOfUsers_thenCorrect () {רשימה params = ArrayList חדש (); params.add (SearchCriteria חדשה ("firstName", ":", "John")); params.add (חדש SearchCriteria ("lastName", ":", "Doe")); תוצאות רשימה = userApi.searchUser (params); assertThat (userJohn, isIn (תוצאות)); assertThat (userTom, not (isIn (results))); }
הבא, בואו נקבל רשימה שֶׁל מִשׁתַמֵשׁ עם אותו הדבר שם משפחה:
@Test הציבור בטל givenLast_whenGettingListOfUsers_thenCorrect () {רשימה params = ArrayList חדש (); params.add (חדש SearchCriteria ("lastName", ":", "Doe")); תוצאות רשימה = userApi.searchUser (params); assertThat (userJohn, isIn (תוצאות)); assertThat (userTom, isIn (תוצאות)); }
לאחר מכן, בואו נקבל משתמשים עם גילגדול או שווה 25:
@Test הציבור בטל givenLastAndAge_whenGettingListOfUsers_thenCorrect () {רשימה params = ArrayList חדש (); params.add (חדש SearchCriteria ("lastName", ":", "Doe")); params.add (SearchCriteria חדשה ("גיל", ">", "25")); תוצאות רשימה = userApi.searchUser (params); assertThat (userTom, isIn (תוצאות)); assertThat (userJohn, not (isIn (results))); }
לאחר מכן, בואו נחפש משתמשים לא ממש קיימים:
@Test הציבור בטל givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect () {רשימה params = ArrayList חדש (); params.add (SearchCriteria חדשה ("שם ראשון", ":", "אדם")); params.add (חדש SearchCriteria ("lastName", ":", "Fox")); תוצאות רשימה = userApi.searchUser (params); assertThat (userJohn, not (isIn (results))); assertThat (userTom, not (isIn (results))); }
לבסוף, בואו נחפש משתמשים שניתנו בלבד חלקישם פרטי:
@Test public void givenPartialFirst_whenGettingListOfUsers_thenCorrect () {List params = ArrayList new (); params.add (SearchCriteria חדשה ("firstName", ":", "jo")); תוצאות רשימה = userApi.searchUser (params); assertThat (userJohn, isIn (תוצאות)); assertThat (userTom, not (isIn (results))); }
6. ה UserController
לבסוף, בואו נחבר כעת את תמיכת ההתמדה לחיפוש גמיש זה ל- API של REST שלנו.
אנחנו הולכים להקים פשוט UserController - עם מצא הכל()משתמש ב "לחפש”להעביר את כל ביטוי החיפוש / סינון:
@Controller UserController בכיתה ציבורית {@ ממשק API IUserDao פרטי; @RequestMapping (method = RequestMethod.GET, value = "/ users") @ResponseBody public List FindAll (@RequestParam (value = "search", required = false) חיפוש מחרוזות) {List params = ArrayList new (); אם (חיפוש! = null) {תבנית תבנית = תבנית. קומפילציה ("(\ w +?) (: |) (\ w +?),"); התאמת התאמה = דפוס. התאמה (חיפוש + ","); בעוד (matcher.find ()) {params.add (SearchCriteria חדש (matcher.group (1), matcher.group (2), matcher.group (3))); }} להחזיר api.searchUser (params); }}
שים לב כיצד אנו פשוט יוצרים אובייקטים בקריטריון החיפוש שלנו מתוך ביטוי החיפוש.
כעת אנו בנקודה בה אנו יכולים להתחיל לשחק עם ה- API ולוודא שהכל עובד כראוי:
// localhost: 8080 / משתמשים? search = lastName: איילה, גיל> 25
והנה תגובתה:
[{"id": 2, "firstName": "tom", "lastName": "doe", "email": "[email protected]", "age": 26}]
7. מסקנה
יישום פשוט אך חזק זה מאפשר לא מעט סינון חכם ב- API של REST. כן - הוא עדיין מחוספס בקצוות וניתן לשפר אותו (וישתפר במאמר הבא) - אך זו נקודת מוצא מוצקה ליישום פונקציונליות סינון מסוג זה בממשקי ה- API שלכם.
ה יישום מלא של מאמר זה ניתן למצוא בפרויקט GitHub - זהו פרויקט מבוסס Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.
הַבָּא » שפת שאילתת REST עם מפרט JPA של נתוני אביב