מדריך לג'דבי

1. הקדמה

במאמר זה נבחן כיצד לבצע שאילתות על מסד נתונים יחסי עם jdbi.

Jdbi היא ספריית Java פתוחה (רישיון אפאצ'י) המשתמשת בביטויי lambda ובהשתקפות בכדי לספק ממשק ידידותי וברמה גבוהה יותר מאשר JDBC לגישה למסד הנתונים.

Jdbi, לעומת זאת, אינו ORM; למרות שיש לו מודול מיפוי אופציונלי ל- SQL, אין לו הפעלה עם אובייקטים מצורפים, שכבת עצמאות מסד נתונים וכל פעמונים ושריקות אחרות של ORM אופייני.

2. הגדרת Jdbi

Jdbi מאורגן לליבה ולמספר מודולים אופציונליים.

כדי להתחיל, עלינו רק לכלול את מודול הליבה בתלות שלנו:

  org.jdbi jdbi3-core 3.1.0 

במהלך מאמר זה נציג דוגמאות באמצעות בסיס הנתונים של HSQL:

 org.hsqldb hsqldb 2.4.0 מבחן 

אנו יכולים למצוא את הגרסה האחרונה של jdbi3-core, HSQLDB ושאר המודולים של Jdbi ב- Maven Central.

3. חיבור למסד הנתונים

ראשית, עלינו להתחבר למסד הנתונים. לשם כך עלינו לציין את פרמטרי החיבור.

נקודת המוצא היא ג'דבי מעמד:

Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", "");

כאן אנו מציינים את כתובת האתר של החיבור, שם משתמש וכמובן סיסמה.

3.1. פרמטרים נוספים

אם עלינו לספק פרמטרים אחרים, אנו משתמשים בשיטה עמוסת יתר המקבלת א נכסים לְהִתְנַגֵד:

מאפייני מאפיינים = מאפיינים חדשים (); properties.setProperty ("שם משתמש", "sa"); properties.setProperty ("סיסמה", ""); Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", מאפיינים);

בדוגמאות אלה שמרנו את ה- ג'דבי למשל במשתנה מקומי. הסיבה לכך היא שנשתמש בו לשליחת הצהרות ושאילתות למסד הנתונים.

למעשה, רק להתקשר לִיצוֹר אינו יוצר שום קשר ל- DB. זה פשוט שומר את פרמטרי החיבור למועד מאוחר יותר.

3.2. באמצעות א מקור מידע

אם אנו מתחברים למסד הנתונים באמצעות מקור מידע, כפי שקורה בדרך כלל, נוכל להשתמש במתאים לִיצוֹר להעמיס יותר מדי:

Jdbi jdbi = Jdbi.create (מקור נתונים);

3.3. עבודה עם ידיות

חיבורים בפועל למסד הנתונים מיוצגים על ידי מקרים של ידית מעמד.

הדרך הקלה ביותר לעבוד עם ידיות ולסגור אותן באופן אוטומטי, היא באמצעות ביטויים למבדה:

jdbi.useHandle (ידית -> {doStuffWith (ידית);});

אנו קוראים useHandle כשאנחנו לא צריכים להחזיר ערך.

אחרת, אנו משתמשים withHandle:

jdbi.withHandle (ידית -> {החזר computeValue (ידית);});

אפשר גם, אם כי לא מומלץ, לפתוח ידנית ידית חיבור; במקרה כזה, עלינו לסגור את זה כשתסיים:

Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", ""); נסה (ידית ידית = jdbi.open ()) {doStuffWith (ידית); }

למרבה המזל, כפי שאנו רואים, ידית מכשירים סגור, כך שניתן להשתמש בו עם נסי משאבים.

4. הצהרות פשוטות

עכשיו כשאנחנו יודעים להשיג חיבור בואו נראה איך להשתמש בו.

בחלק זה ניצור טבלה פשוטה בה נשתמש לאורך המאמר.

לשלוח הצהרות כגון ליצור שולחן למסד הנתונים, אנו משתמשים ב- לבצע שיטה:

handle.execute ("צור פרויקט טבלה" + "(זהות שלמה מזהה, שם varchar (50), url varchar (100))");

לבצע מחזיר את מספר השורות שהושפעו מההצהרה:

int updateCount = handle.execute ("הכנס לערכי הפרויקט" + "(1, 'tutorials', 'github.com/eugenp/tutorials')"); assertEquals (1, updateCount);

למעשה, ביצוע הוא רק שיטת נוחות.

נבחן מקרי שימוש מורכבים יותר בחלקים מאוחרים יותר, אך לפני שנעשה זאת, עלינו ללמוד כיצד לחלץ תוצאות ממסד הנתונים.

5. שאילתת מסד הנתונים

הביטוי הכי פשוט שמייצר תוצאות מה- DB הוא שאילתת SQL.

כדי להנפיק שאילתה עם Jdbi Handle, עלינו, לפחות:

  1. צור את השאילתה
  2. בחר כיצד לייצג כל שורה
  3. לחזור על התוצאות

כעת נסתכל על כל אחת מהנקודות לעיל.

5.1. יצירת שאילתה

באופן לא מפתיע, Jdbi מייצג שאילתות כמופעים של שאילתא מעמד.

אנו יכולים להשיג אחת מהידית:

שאילתת שאילתה = handle.createQuery ("בחר * מתוך פרויקט");

5.2. מיפוי התוצאות

Jdbi מופשט הרחק JDBC ResultSet, שיש לו ממש API מסורבל.

לכן, הוא מציע מספר אפשרויות לגשת לעמודות הנובעות משאילתה או הצהרה אחרת המחזירה תוצאה. כעת נראה את הפשוטים ביותר.

אנו יכולים לייצג כל שורה כמפה:

query.mapToMap ();

מקשי המפה יהיו שמות העמודות שנבחרו.

לחלופין, כאשר שאילתה מחזירה עמודה אחת, אנו יכולים למפות אותה לסוג ה- Java הרצוי:

handle.createQuery ("בחר שם מפרויקט"). mapTo (String.class);

לג'דבי יש מיפוי מובנה לכיתות נפוצות רבות. אלה הספציפיים לספרייה או למערכת בסיס נתונים כלשהם ניתנים במודולים נפרדים.

כמובן, אנו יכולים גם להגדיר ולרשום את המפות שלנו. נדבר על זה בחלק מאוחר יותר.

לבסוף, אנו יכולים למפות שורות לשעועית או למחלקה אישית אחרת. שוב נראה את האפשרויות המתקדמות יותר בקטע ייעודי.

5.3. התבוסס על התוצאות

לאחר שהחלטנו כיצד למפות את התוצאות על ידי קריאה לשיטה המתאימה, אנו מקבלים א תוצאה ניתנת לאיכות לְהִתְנַגֵד.

לאחר מכן נוכל להשתמש בו כדי לחזור על התוצאות, שורה אחת בכל פעם.

כאן נבחן את האפשרויות הנפוצות ביותר.

אנחנו יכולים רק לצבור את התוצאות ברשימה:

רשימה תוצאות = query.mapToMap (). רשימה ();

או לאחר אוסף סוּג:

תוצאות רשימה = query.mapTo (String.class) .collect (Collectors.toSet ());

או שאנחנו יכולים לחזור על התוצאות כזרם:

query.mapTo (String.class) .useStream ((זרם זרם) -> {doStuffWith (זרם)});

כאן הקלדנו את ה- זרם משתנה לשם הבהרה, אך אין צורך לעשות זאת.

5.4. השגת תוצאה יחידה

במקרה מיוחד, כאשר אנו מצפים או מעוניינים בשורה אחת בלבד, יש לנו כמה שיטות ייעודיות.

אם אנחנו רוצים לכל היותר תוצאה אחת, אנחנו יכולים להשתמש findFirst:

אופציונאלי ראשון = query.mapToMap (). findFirst ();

כפי שאנו רואים, הוא מחזיר אופציונאלי ערך, שנמצא רק אם השאילתה מחזירה לפחות תוצאה אחת.

אם השאילתה מחזירה יותר משורה אחת, רק הראשונה מוחזרת.

אם במקום זאת, אנחנו רוצים תוצאה אחת ויחידה, אנו משתמשים מצא רק:

תאריך onlyResult = query.mapTo (Date.class) .findOnly ();

לבסוף, אם יש אפס תוצאות או יותר מאחת, מצא רק זורק IllegalStateException.

6. פרמטרים מחייבים

לעתים קרובות, לשאילתות יש חלק קבוע וחלק פרמטרי. יש לכך מספר יתרונות, כולל:

  • אבטחה: על ידי הימנעות משרשור מחרוזות, אנו מונעים הזרקת SQL
  • קלות: אנחנו לא צריכים לזכור את התחביר המדויק של סוגי נתונים מורכבים כגון חותמות זמן
  • ביצועים: ניתן לנתח את החלק הסטטי של השאילתה פעם אחת ולשמור אותו במטמון

Jdbi תומך הן בפרמטרים במיקום והן בפרמטרים בשם.

אנו מכניסים פרמטרים מיקום כסימני שאלה בשאילתה או בהצהרה:

שאילתה positionalParamsQuery = handle.createQuery ("בחר * מתוך הפרויקט שבו שם =?");

פרמטרים בשם, במקום זאת, התחל עם נקודתיים:

שאילתה בשם ParamsQuery = handle.createQuery ("בחר * מתוך פרויקט שבו כתובת האתר כמו: תבנית");

בשני המקרים, כדי להגדיר את הערך של פרמטר, אנו משתמשים באחת הגרסאות של לִקְשׁוֹר שיטה:

positionalParamsQuery.bind (0, "מדריכים"); בשםParamsQuery.bind ("דפוס", "% github.com / eugenp /%");

שים לב שבניגוד ל- JDBC, אינדקסים מתחילים ב -0.

6.1. קשירת פרמטרים מרובים בשם בבת אחת

אנו יכולים גם לאגד מספר פרמטרים בשם יחד באמצעות אובייקט.

נניח שיש לנו את השאילתה הפשוטה הזו:

שאילתת שאילתה = handle.createQuery ("בחר מזהה מהפרויקט שבו שם =: שם ו- url =: url"); Params מפה = HashMap חדש (); params.put ("שם", "מנוחה עם אביב"); params.put ("url", "github.com/eugenp/REST-With-Spring");

ואז, למשל, נוכל להשתמש במפה:

query.bindMap (params);

או שאנחנו יכולים להשתמש באובייקט בדרכים שונות. הנה, למשל, אנו קושרים אובייקט העוקב אחר מוסכמת JavaBean:

query.bindBean (paramsBean);

אך אנו יכולים גם לקשור שדות או שיטות של אובייקט; לקבלת כל האפשרויות הנתמכות, עיין בתיעוד Jdbi.

7. הוצאת הצהרות מורכבות יותר

כעת, לאחר שראינו שאילתות, ערכים ופרמטרים, אנו יכולים לחזור להצהרות וליישם את אותו הידע.

נזכיר כי לבצע שיטה שראינו קודם היא פשוט קיצור דרך שימושי.

למעשה, בדומה לשאילתות, הצהרות DDL ו- DML מיוצגות כמופעים של הכיתה עדכון.

אנו יכולים להשיג אחת על ידי קריאה לשיטה createUpdate על ידית:

עדכון עדכון = handle.createUpdate ("INSERT INTO PROJECT (NAME, URL) VALUES (: name,: url)");

ואז, על עדכון יש לנו את כל שיטות הכריכה שיש לנו בא שאילתאלכן סעיף 6. חל גם על עדכונים. url

הצהרות מבוצעות כשאנחנו מתקשרים, מפתיעים, לבצע:

int שורות = update.execute ();

כפי שכבר ראינו, הוא מחזיר את מספר השורות המושפעות.

7.1. חילוץ ערכי עמודות לעלייה אוטומטית

כמקרה מיוחד, כאשר יש לנו משפט להוסיף עם עמודות שנוצרו אוטומטית (בדרך כלל תוספת אוטומטית או רצפים), ייתכן שנרצה להשיג את הערכים שנוצרו.

ואז, אנחנו לא מתקשרים לבצע, אבל executeAndReturnGeneratedKeys:

עדכון עדכון = handle.createUpdate ("INSERT INTO PROJECT (NAME, URL)" + "VALUES ('tutorials', 'github.com/eugenp/tutorials')"); ResultBearing generatedKeys = update.executeAndReturnGeneratedKeys ();

תוצאה נושאת הוא אותו ממשק המיושם על ידי שאילתא מעמד שראינו בעבר, אז אנחנו כבר יודעים להשתמש בזה:

generatedKeys.mapToMap () .findOnly (). get ("id");

8. עסקאות

אנו זקוקים לעסקה בכל פעם שנצטרך לבצע הצהרות מרובות כפעולה אטומית אחת.

כמו בידיות חיבור, אנו מציגים עסקה על ידי קריאה לשיטה עם סגירה:

handle.useTransaction ((ידית h) -> {haveFunWith (h);});

וכמו בידיות, העסקה נסגרת אוטומטית עם חזרת הסגירה.

עם זאת, עלינו לבצע את העסקה או להחזיר אותה לאחור לפני החזרה:

handle.useTransaction ((ידית h) -> {h.execute ("..."); h.commit ();});

עם זאת, אם יוצא חריג מהסגירה, ג'דבי מחזיר את העסקה אוטומטית.

כמו בידיות, יש לנו שיטה ייעודית, בעסקה, אם אנחנו רוצים להחזיר משהו מהסגירה:

handle.inTransaction ((Handle h) -> {h.execute ("..."); h.commit (); return true;});

8.1. ניהול עסקאות ידני

למרות שבמקרה הכללי זה לא מומלץ, אנחנו יכולים לעשות זאת התחל ו סגור עסקה באופן ידני:

handle.begin (); // ... handle.commit (); handle.close ();

9. מסקנות וקריאה נוספת

במדריך זה הצגנו את הליבה של Jdbi: שאילתות, הצהרות ועסקאות.

השארנו כמה תכונות מתקדמות, כגון מיפוי שורות ועמודות מותאמות אישית ועיבוד אצווה.

כמו כן, לא דנו באף אחד מהמודולים האופציונליים, ובעיקר בסיומת אובייקט SQL.

הכל מוצג בפירוט בתיעוד Jdbi.

ניתן למצוא את היישום של כל הדוגמאות וקטעי הקוד בפרויקט GitHub - זהו פרויקט של Maven, כך שיהיה קל לייבא ולהפעיל אותו כמות שהוא.


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