שפת שאילתת REST עם קריטריוני אביב ו- JPA

REST למעלה

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 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 של נתוני אביב

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

$config[zx-auto] not found$config[zx-overlay] not found