מבוא ל- JDBC

ג'אווה טופ

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

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

1. סקירה כללית

במאמר זה נבחן את JDBC (Java Database Connectivity) שהוא ממשק API לחיבור וביצוע שאילתות במסד נתונים.

JDBC יכול לעבוד עם כל בסיס נתונים כל עוד מסופקים מנהלי התקנים מתאימים.

2. נהגי JDBC

מנהל התקן JDBC הוא יישום API של JDBC המשמש לחיבור לסוג מסד נתונים מסוים. ישנם מספר סוגים של מנהלי התקנים של JDBC:

  • סוג 1 - מכיל מיפוי ל- API אחר לגישה לנתונים; דוגמה לכך היא מנהל ההתקן JDBC-ODBC
  • סוג 2 - הוא יישום המשתמש בספריות בצד הלקוח של מאגר היעד; נקרא גם מנהל התקן API מקורי
  • סוג 3 - משתמש בתוכנת ביניים כדי להמיר שיחות JDBC לשיחות ספציפיות למסד נתונים; ידוע גם כמנהל פרוטוקול רשת
  • סוג 4 - התחבר ישירות למסד נתונים על ידי המרת שיחות JDBC לשיחות ספציפיות למסד נתונים; המכונה מנהלי התקני פרוטוקול מסד נתונים או מנהלי התקנים דקים,

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

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

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

3.1. רישום הנהג

לדוגמא, נשתמש במנהל התקן של פרוטוקול מסד נתונים מסוג 4.

מכיוון שאנחנו משתמשים במסד נתונים של MySQL, אנו זקוקים ל- mysql-connector-java תלות:

 mysql mysql-connector-java 6.0.6 

לאחר מכן, בוא נרשום את מנהל ההתקן באמצעות ה- Class.forName () שיטה, הטוענת באופן דינמי את מחלקת הנהגים:

Class.forName ("com.mysql.cj.jdbc.Driver");

בגרסאות ישנות יותר של JDBC, לפני שהשגנו חיבור, היינו צריכים לאתחל את מנהל ההתקן JDBC על ידי התקשרות ל- Class.forName שיטה. נכון ל- JDBC 4.0, כל הנהגים שנמצאים בשביל הכיתה נטענים אוטומטית. לכן, לא נצטרך את זה Class.forName חלק בסביבות מודרניות.

3.2. יצירת החיבור

כדי לפתוח חיבור, נוכל להשתמש ב- getConnection () שיטה של DriverManager מעמד. שיטה זו דורשת כתובת אתר לחיבור חוּט פָּרָמֶטֶר:

נסה (Connection con = DriverManager .getConnection ("jdbc: mysql: // localhost: 3306 / myDb", "user1", "pass")) {// השתמש ב- con כאן}

מאז חיבור הוא ניתן לסגירה אוטומטית המשאב, עלינו להשתמש בו בתוך a נסה עם משאבים לַחסוֹם.

התחביר של כתובת ה- URL לחיבור תלוי בסוג מסד הנתונים בו משתמשים. בואו נסתכל על כמה דוגמאות:

jdbc: mysql: // localhost: 3306 / myDb? user = user1 & password = pass
jdbc: postgresql: // localhost / myDb
jdbc: hsqldb: mem: myDb

כדי להתחבר למפורט myDb מסד נתונים, נצטרך ליצור את מסד הנתונים ומשתמש ולהוסיף גישה נדרשת:

צור נתונים myDb; צור משתמש 'משתמש 1' שזוהה על ידי 'מעבר'; הענק הכל ב- myDb. * ל- 'user1';

4. ביצוע הצהרות SQL

הוראות SQL לשלוח למסד הנתונים, אנו יכולים להשתמש במופעים מהסוג הַצהָרָה, הצהרה מוכנה, אוֹ CallableStatement, שניתן להשיג באמצעות חיבור לְהִתְנַגֵד.

4.1. הַצהָרָה

ה הַצהָרָה הממשק מכיל את הפונקציות החיוניות לביצוע פקודות SQL.

ראשית, בואו ניצור a הַצהָרָה לְהִתְנַגֵד:

נסה (הצהרה stmt = con.createStatement ()) {// השתמש ב- stmt כאן}

שוב, אנחנו צריכים לעבוד עם הַצהָרָהs בתוך a נסה עם משאבים לחסום לניהול משאבים אוטומטי.

בכל מקרה, ביצוע הוראות SQL יכול להיעשות באמצעות שלוש שיטות:

  • לבצע שאילתה() להוראות SELECT
  • executeUpdate () לעדכון הנתונים או מבנה מסד הנתונים
  • לבצע() ניתן להשתמש בשני המקרים לעיל כאשר התוצאה אינה ידועה

בואו נשתמש ב- לבצע() שיטה להוסיף א סטודנטים טבלה למסד הנתונים שלנו:

String tableSql = "צור טבלה אם לא קיים עובדים" + "(emp_id int PRIMARY KEY AUTO_INCREMENT, שם varchar (30)," + "position varchar (30), שכר כפול)"; stmt.execute (tableSql);

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

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

אם הערך הוא -1, הפקודה הייתה שאילתת SELECT; לאחר מכן נוכל להשיג את התוצאה באמצעות stmt.getResultSet ().

לאחר מכן, בואו להוסיף רשומה לטבלה שלנו באמצעות ה- executeUpdate () שיטה:

מחרוזת insertSql = "הכנס לעובדים (שם, תפקיד, משכורת)" + "ערכים ('ג'ון', 'מפתח', 2000)"; stmt.executeUpdate (insertSql);

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

אנו יכולים לאחזר את הרשומות מהטבלה באמצעות ה- לבצע שאילתה() שיטה המחזירה אובייקט מסוג ResultSet:

מחרוזת selectSql = "בחר * מעובדים"; נסה (ResultSet resultSet = stmt.executeQuery (selectSql)) {// השתמש ב- resultSet כאן}

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

4.2. הצהרה מוכנה

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

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

מחרוזת updatePositionSql = "עדכן עובדים להגדיר מיקום =? איפה emp_id =?"; נסה (PreparedStatement pstmt = con.prepareStatement (updatePositionSql)) {// השתמש ב- pstmt כאן}

כדי להוסיף פרמטרים ל הצהרה מוכנה, אנו יכולים להשתמש בקובעים פשוטים - setX () - כאשר X הוא סוג הפרמטר, וטיעוני השיטה הם הסדר והערך של הפרמטר:

pstmt.setString (1, "מפתח מוביל"); pstmt.setInt (2, 1);

ההצהרה מבוצעת באחת מאותן שלוש שיטות שתוארו קודם: executeQuery (), executeUpdate (), execute () בלי ה- SQL חוּט פָּרָמֶטֶר:

int rowsAffected = pstmt.executeUpdate ();

4.3. CallableStatement

ה CallableStatement ממשק מאפשר שיחות נהלים מאוחסנים.

ליצור CallableStatement אנו יכולים להשתמש ב- preparCall () שיטה של חיבור:

מחרוזת preparedSql = "{call insertEmployee (?,?,?,?)}"; נסה (CallableStatement cstmt = con.prepareCall (preparedSql)) {// השתמש ב- cstmt כאן}

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

cstmt.setString (2, "ana"); cstmt.setString (3, "בודק"); cstmt.setDouble (4, 2000);

אם לפרוצדורה המאוחסנת יש פרמטרי פלט, עלינו להוסיף אותם באמצעות ה- registerOutParameter () שיטה:

cstmt.registerOutParameter (1, Types.INTEGER);

אז בוא נבצע את המשפט ונשיג את הערך המוחזר באמצעות מקביל getX () שיטה:

cstmt.execute (); int new_id = cstmt.getInt (1);

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

מפריד // צור נוהל insertEm עובד (OUT emp_id int, IN emp_name varchar (30), IN position varchar (30), IN משכורת כפולה) התחל להכניס לעובדים (שם, תפקיד, משכורת) ערכים (emp_name, תפקיד, משכורת); SET emp_id = LAST_INSERT_ID (); END // תיחום;

ה להוסיף עובד ההליך לעיל יוסיף רשומה חדשה ב- עובדים טבלה באמצעות הפרמטרים הנתונים והחזיר את מזהה הרשומה החדשה ב- אמפ_יד פרמטר החוצה.

כדי להיות מסוגל להריץ נוהל מאוחסן מג'אווה, על משתמש החיבור להיות בעל גישה למטא נתונים של ההליך המאוחסן. ניתן להשיג זאת על ידי מתן זכויות למשתמש בכל ההליכים המאוחסנים בכל בסיסי הנתונים:

הענק הכל על mysql.proc ל 'user1';

לחלופין, אנו יכולים לפתוח את הקשר עם הנכס noAccessToProcedureBodies מכוון ל נָכוֹן:

con = DriverManager.getConnection ("jdbc: mysql: // localhost: 3306 / myDb? noAccessToProcedureBodies = true", "user1", "pass");

זה יודיע ל- API של JDBC כי למשתמש אין את הזכויות לקרוא את מטא-הנתונים של ההליך כך שייצור את כל הפרמטרים כ- INOUT חוּט פרמטרים.

5. ניתוח תוצאות השאילתות

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

5.1. ResultSet מִמְשָׁק

ה ResultSet משתמש ב- הַבָּא() שיטה לעבור לשורה הבאה.

בואו ניצור תחילה עוֹבֵד בכיתה לאחסון הרשומות שאוחזרו:

עובד בכיתה ציבורית {מזהה פרטי פרטי; שם מחרוזת פרטי; תפקיד מחרוזת פרטי; משכורת כפולה פרטית; // קונסטרוקטור סטנדרטי, גטרים, סטרים}

לאחר מכן, בוא נחצה את ResultSet וליצור עוֹבֵד אובייקט לכל רשומה:

מחרוזת selectSql = "בחר * מעובדים"; נסה (ResultSet resultSet = stmt.executeQuery (selectSql)) {רשימת עובדים = ArrayList חדש (); בעוד (resultSet.next ()) {עובד אמפ = עובד חדש (); emp.setId (resultSet.getInt ("emp_id")); emp.setName (resultSet.getString ("שם")); emp.setPosition (resultSet.getString ("עמדה")); emp.setSalary (resultSet.getDouble ("משכורת")); עובדים. להוסיף (אמפ); }}

אחזור הערך עבור כל תא טבלה יכול להיעשות בשיטות סוג getX () כאשר X מייצג את סוג נתוני התא.

ה getX () ניתן להשתמש בשיטות עם int פרמטר המייצג את סדר התא, או a חוּט פרמטר המייצג את שם העמודה. האפשרות האחרונה עדיפה במקרה שנשנה את סדר העמודות בשאילתה.

5.2. ניתן לעדכן ResultSet

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

אם אנחנו רוצים להשתמש ב- ResultSet כדי לעדכן נתונים ולעבור אותם לשני הכיוונים, עלינו ליצור את ה- הַצהָרָה אובייקט עם פרמטרים נוספים:

stmt = con.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

לנווט מסוג זה ResultSetנוכל להשתמש באחת מהשיטות:

  • first (), last (), beforeFirst (), beforeLast () - לעבור לשורה הראשונה או האחרונה של א ResultSet או לקו שלפני אלה
  • הקודם הבא() - לנווט קדימה ואחורה ב ResultSet
  • getRow () - כדי להשיג את מספר השורה הנוכחי
  • moveToInsertRow (), moveToCurrentRow () - לעבור לשורה ריקה חדשה להכניס ובחזרה לשורה הנוכחית אם בשורה חדשה
  • מוחלט (שורה int) - כדי לעבור לשורה שצוינה
  • קרוב משפחה (int nrRows) - כדי להזיז את הסמן את מספר השורות הנתון

מעדכן את ResultSet ניתן לעשות זאת באמצעות שיטות עם הפורמט updateX () כאשר X הוא סוג נתוני התאים. שיטות אלה רק מעדכנות את ResultSet אובייקט ולא טבלאות מסד הנתונים.

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

  • updateRow () - להתמיד בשינויים בשורה הנוכחית במסד הנתונים
  • insertRow (), deleteRow () - כדי להוסיף שורה חדשה או למחוק את השורה הנוכחית ממסד הנתונים
  • refreshRow () - לרענן את ResultSet עם כל שינוי במסד הנתונים
  • cancelRowUpdates () - לביטול שינויים שבוצעו בשורה הנוכחית

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

נסה (הצהרה updatableStmt = con.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) {try (ResultSet updatableResultSet = updatableStmt.executeQuery (selectSql)) {updatableResultInsSet.move; updatableResultSet.updateString ("שם", "סימן"); updatableResultSet.updateString ("עמדה", "אנליסט"); updatableResultSet.updateDouble ("משכורת", 2000); updatableResultSet.insertRow (); }}

6. ניתוח מטא-נתונים

ממשק ה- API של JDBC מאפשר לחפש מידע על מסד הנתונים, הנקרא מטא-נתונים.

6.1. DatabaseMetadata

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

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

DatabaseMetaData dbmd = con.getMetaData (); ResultSet tablesResultSet = dbmd.getTables (null, null, "%", null); בעוד (tablesResultSet.next ()) {LOG.info (tablesResultSet.getString ("TABLE_NAME")); }

6.2. ResultSetMetadata

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

ResultSetMetaData rsmd = rs.getMetaData (); int nrColumn = rsmd.getColumnCount (); IntStream.range (1, nrColumn) .forEach (i -> {נסה {LOG.info (rsmd.getColumnName (i));} לתפוס (SQLException e) {e.printStackTrace ();}});

7. טיפול בעסקאות

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

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

ראשית, עלינו להגדיר את התחייבות אוטומטית רכוש של חיבור ל שֶׁקֶרואז השתמש ב- לְבַצֵעַ() ו גלגל לאחור() שיטות לשלוט בעסקה.

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

מחרוזת updatePositionSql = "עדכן עובדים להגדיר מיקום =? איפה emp_id =?"; PreparedStatement pstmt = con.prepareStatement (updatePositionSql); pstmt.setString (1, "מפתח מוביל"); pstmt.setInt (2, 1); מחרוזת updateSalarySql = "עדכן עובדים משכורת מוגדרת =? איפה emp_id =?"; PreparedStatement pstmt2 = con.prepareStatement (updateSalarySql); pstmt.setDouble (1, 3000); pstmt.setInt (2, 1); autoCommit בוליאני = con.getAutoCommit (); נסה את {con.setAutoCommit (false); pstmt.executeUpdate (); pstmt2.executeUpdate (); con.commit (); } לתפוס (SQLException exc) {con.rollback (); } סוף סוף {con.setAutoCommit (autoCommit); }

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

8. סגירת המשאבים

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

אנו יכולים לעשות זאת באמצעות ה- סגור() ממשק API:

con.close ();

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

הדבר נכון גם לגבי הַצהָרָהs, הצהרה מוכנהs, CallableStatements, ו ResultSetס.

9. מסקנה

במדריך זה הסתכלנו על יסודות העבודה עם ממשק ה- API של JDBC.

כמו תמיד, ניתן למצוא את קוד המקור המלא של הדוגמאות ב- GitHub.

תחתית Java

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

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

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