JDBC - Hướng dẫn nhanh

JDBC là gì?

JDBC là viết tắt của Java Database Connectivity, là một API Java tiêu chuẩn để kết nối độc lập với cơ sở dữ liệu giữa ngôn ngữ lập trình Java và nhiều loại cơ sở dữ liệu.

Thư viện JDBC bao gồm các API cho từng tác vụ thường được kết hợp với việc sử dụng cơ sở dữ liệu:

  • Tạo kết nối với cơ sở dữ liệu

  • Tạo câu lệnh SQL hoặc MySQL

  • Thực thi truy vấn SQL hoặc MySQL trong cơ sở dữ liệu

  • Xem & Sửa đổi các bản ghi kết quả

Điều kiện tiên quyết:

Bạn cần hiểu rõ về hai chủ đề sau để học JDBC:

  • Lập trình JAVA cốt lõi

  • Cơ sở dữ liệu SQL hoặc MySQL

JDBC - Thiết lập Môi trường:

Đảm bảo rằng bạn đã thực hiện thiết lập sau:

  • Cài đặt JAVA lõi

  • Cài đặt cơ sở dữ liệu SQL hoặc MySQL

Ngoài những điều trên, bạn cần thiết lập một cơ sở dữ liệu mà bạn sẽ sử dụng cho dự án của mình. Giả sử đây là EMP và bạn đã tạo Nhân viên trên bảng trong cùng một cơ sở dữ liệu.

Tạo ứng dụng JDBC:

Có sáu bước liên quan đến việc xây dựng một ứng dụng JDBC mà tôi sẽ trình bày ngắn gọn trong hướng dẫn này:

Nhập các gói:

Điều này yêu cầu bạn bao gồm các gói chứa các lớp JDBC cần thiết cho lập trình cơ sở dữ liệu. Thông thường, sử dụng import java.sql. * Sẽ đủ như sau:

//STEP 1. Import required packages
import java.sql.*;

Đăng ký trình điều khiển JDBC:

Điều này yêu cầu bạn khởi tạo trình điều khiển để bạn có thể mở kênh liên lạc với cơ sở dữ liệu. Sau đây là đoạn mã để đạt được điều này:

//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");

Mở kết nối:

Điều này yêu cầu sử dụng phương thức DriverManager.getConnection () để tạo một đối tượng Connection, đại diện cho một kết nối vật lý với cơ sở dữ liệu như sau:

//STEP 3: Open a connection
//  Database credentials
static final String USER = "username";
static final String PASS = "password";
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);

Thực hiện một truy vấn:

Điều này yêu cầu sử dụng một đối tượng kiểu Statement hoặc PreparedStatement để xây dựng và gửi một câu lệnh SQL tới cơ sở dữ liệu như sau:

//STEP 4: Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql;
sql = "SELECT id, first, last, age FROM Employees";
ResultSet rs = stmt.executeQuery(sql);

Nếu có câu lệnh SQL UPDATE, INSERT hoặc DELETE được yêu cầu, thì đoạn mã sau sẽ là bắt buộc:

//STEP 4: Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql;
sql = "DELETE FROM Employees";
ResultSet rs = stmt.executeUpdate(sql);

Trích xuất dữ liệu từ tập kết quả:

Bước này là bắt buộc trong trường hợp bạn đang tìm nạp dữ liệu từ cơ sở dữ liệu. Bạn có thể sử dụng phương thức ResultSet.getXXX () thích hợp để truy xuất dữ liệu từ tập kết quả như sau:

//STEP 5: Extract data from result set
while(rs.next()){
    //Retrieve by column name
    int id  = rs.getInt("id");
    int age = rs.getInt("age");
    String first = rs.getString("first");
    String last = rs.getString("last");

    //Display values
    System.out.print("ID: " + id);
    System.out.print(", Age: " + age);
    System.out.print(", First: " + first);
    System.out.println(", Last: " + last);
}

Làm sạch môi trường:

Bạn nên đóng tất cả các tài nguyên cơ sở dữ liệu một cách rõ ràng thay vì dựa vào bộ sưu tập rác của JVM như sau:

//STEP 6: Clean-up environment
rs.close();
stmt.close();
conn.close();

Chương trình JDBC đầu tiên:

Dựa trên các bước trên, chúng tôi có thể có mã mẫu tổng hợp sau đây mà chúng tôi có thể sử dụng làm mẫu trong khi viết mã JDBC của mình:

Mã mẫu này được viết dựa trên môi trường và thiết lập cơ sở dữ liệu được thực hiện trong chương Môi trường.

//STEP 1. Import required packages
import java.sql.*;

public class FirstExample {
   // JDBC driver name and database URL
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
   static final String DB_URL = "jdbc:mysql://localhost/EMP";

   //  Database credentials
   static final String USER = "username";
   static final String PASS = "password";
   
   public static void main(String[] args) {
   Connection conn = null;
   Statement stmt = null;
   try{
      //STEP 2: Register JDBC driver
      Class.forName("com.mysql.jdbc.Driver");

      //STEP 3: Open a connection
      System.out.println("Connecting to database...");
      conn = DriverManager.getConnection(DB_URL,USER,PASS);

      //STEP 4: Execute a query
      System.out.println("Creating statement...");
      stmt = conn.createStatement();
      String sql;
      sql = "SELECT id, first, last, age FROM Employees";
      ResultSet rs = stmt.executeQuery(sql);

      //STEP 5: Extract data from result set
      while(rs.next()){
         //Retrieve by column name
         int id  = rs.getInt("id");
         int age = rs.getInt("age");
         String first = rs.getString("first");
         String last = rs.getString("last");

         //Display values
         System.out.print("ID: " + id);
         System.out.print(", Age: " + age);
         System.out.print(", First: " + first);
         System.out.println(", Last: " + last);
      }
      //STEP 6: Clean-up environment
      rs.close();
      stmt.close();
      conn.close();
   }catch(SQLException se){
      //Handle errors for JDBC
      se.printStackTrace();
   }catch(Exception e){
      //Handle errors for Class.forName
      e.printStackTrace();
   }finally{
      //finally block used to close resources
      try{
         if(stmt!=null)
            stmt.close();
      }catch(SQLException se2){
      }// nothing we can do
      try{
         if(conn!=null)
            conn.close();
      }catch(SQLException se){
         se.printStackTrace();
      }//end finally try
   }//end try
   System.out.println("Goodbye!");
}//end main
}//end FirstExample

Bây giờ chúng ta hãy biên dịch ví dụ trên như sau:

C:\>javac FirstExample.java
C:\>

Khi bạn chạy FirstExample, nó tạo ra kết quả sau:

C:\>java FirstExample
Connecting to database...
Creating statement...
ID: 100, Age: 18, First: Zara, Last: Ali
ID: 101, Age: 25, First: Mahnaz, Last: Fatma
ID: 102, Age: 30, First: Zaid, Last: Khan
ID: 103, Age: 28, First: Sumit, Last: Mittal
C:\>

Phương pháp SQLException:

SQLException có thể xảy ra cả trong trình điều khiển và cơ sở dữ liệu. Khi một ngoại lệ như vậy xảy ra, một đối tượng kiểu SQLException sẽ được chuyển đến mệnh đề catch.

Đối tượng SQLException đã truyền có sẵn các phương thức sau để truy xuất thông tin bổ sung về ngoại lệ:

phương pháp Sự miêu tả
getErrorCode () Nhận số lỗi liên quan đến ngoại lệ.
getMessage () Nhận thông báo lỗi của trình điều khiển JDBC đối với lỗi do trình điều khiển xử lý hoặc nhận số lỗi Oracle và thông báo về lỗi cơ sở dữ liệu.
getSQLState () Nhận chuỗi SQLstate XOPEN. Đối với lỗi trình điều khiển JDBC, không có thông tin hữu ích nào được trả về từ phương pháp này. Đối với lỗi cơ sở dữ liệu, mã SQLstate XOPEN năm chữ số được trả về. Phương thức này có thể trả về null.
getNextException () Nhận đối tượng Ngoại lệ tiếp theo trong chuỗi ngoại lệ.
printStackTrace () In ngoại lệ hiện tại hoặc có thể ném và dấu vết của nó vào một luồng lỗi chuẩn.
printStackTrace (PrintStream s) In tệp có thể ném này và dấu vết của nó vào luồng in mà bạn chỉ định.
printStackTrace (PrintWriter w) In tệp có thể ném này và dấu vết của nó cho người viết in mà bạn chỉ định.

Bằng cách sử dụng thông tin có sẵn từ đối tượng Exception, bạn có thể bắt một ngoại lệ và tiếp tục chương trình của mình một cách thích hợp. Đây là hình thức chung của khối thử:

try {
   // Your risky code goes between these curly braces!!!
}
catch(Exception ex) {
   // Your exception handling code goes between these 
   // curly braces, similar to the exception clause 
   // in a PL/SQL block.
}
finally {
   // Your must-always-be-executed code goes between these 
   // curly braces. Like closing database connection.
}

JDBC - Loại dữ liệu:

Bảng sau đây tóm tắt kiểu dữ liệu JDBC mặc định mà kiểu dữ liệu Java được chuyển đổi thành khi bạn gọi phương thức setXXX () của đối tượng PreparedStatement hoặc CallableStatement hoặc phương thức ResultSet.updateXXX ().

SQL JDBC / Java setXXX updateXXX
VARCHAR java.lang.String setString updateString
CHAR java.lang.String setString updateString
LONGVARCHAR java.lang.String setString updateString
BIT boolean setBoolean updateBoolean
SỐ java.math.BigDecimal setBigDecimal updateBigDecimal
TINYINT byte setByte updateByte
SMALLINT ngắn setShort updateShort
INTEGER int setInt updateInt
BIGINT Dài setLong updateLong
THỰC TẾ Phao nổi setFloat updateFloat
PHAO NỔI Phao nổi setFloat updateFloat
GẤP ĐÔI gấp đôi setDouble updateDouble
VARBINARY byte [] setBytes updateBytes
BINARY byte [] setBytes updateBytes
NGÀY java.sql.Date đặt ngày cập nhật ngày tháng
THỜI GIAN java.sql.Time cài đặt thời gian cập nhật thời gian
TIMESTAMP java.sql.Timestamp setTimestamp updateTimestamp
CLOB java.sql.Clob setClob updateClob
BÃI java.sql.Blob setBlob updateBlob
MẢNG java.sql.Array setARRAY cập nhật
REF java.sql.Ref SetRef updateRef
CẤU TRÚC java.sql.Struct SetStruct updateStruct

JDBC 3.0 đã hỗ trợ nâng cao cho các kiểu dữ liệu BLOB, CLOB, ARRAY và REF. Đối tượng ResultSet hiện có các phương thức updateBLOB (), updateCLOB (), updateArray () và updateRef () cho phép bạn thao tác trực tiếp dữ liệu tương ứng trên máy chủ.

Phương thức setXXX () và updateXXX () cho phép bạn chuyển đổi các kiểu Java cụ thể thành các kiểu dữ liệu JDBC cụ thể. Các phương thức setObject () và updateObject () cho phép bạn ánh xạ hầu hết mọi kiểu Java sang kiểu dữ liệu JDBC.

Đối tượng ResultSet cung cấp phương thức getXXX () tương ứng cho mỗi kiểu dữ liệu để truy xuất giá trị cột. Mỗi phương thức có thể được sử dụng với tên cột hoặc theo vị trí thứ tự của nó.

SQL JDBC / Java setXXX getXXX
VARCHAR java.lang.String setString getString
CHAR java.lang.String setString getString
LONGVARCHAR java.lang.String setString getString
BIT boolean setBoolean getBoolean
SỐ java.math.BigDecimal setBigDecimal getBigDecimal
TINYINT byte setByte getByte
SMALLINT ngắn setShort getShort
INTEGER int setInt getInt
BIGINT Dài setLong getLong
THỰC TẾ Phao nổi setFloat getFloat
PHAO NỔI Phao nổi setFloat getFloat
GẤP ĐÔI gấp đôi setDouble getDouble
VARBINARY byte [] setBytes getBytes
BINARY byte [] setBytes getBytes
NGÀY java.sql.Date đặt ngày hẹn gặp
THỜI GIAN java.sql.Time cài đặt thời gian dành thời gian
TIMESTAMP java.sql.Timestamp setTimestamp getTimestamp
CLOB java.sql.Clob setClob getClob
BÃI java.sql.Blob setBlob getBlob
MẢNG java.sql.Array setARRAY getARRAY
REF java.sql.Ref SetRef getRef
CẤU TRÚC java.sql.Struct SetStruct getStruct

JDBC - Xử lý hàng loạt:

Xử lý hàng loạt cho phép bạn nhóm các câu lệnh SQL liên quan thành một lô và gửi chúng bằng một lệnh gọi đến cơ sở dữ liệu.

Khi bạn gửi một số câu lệnh SQL đến cơ sở dữ liệu cùng một lúc, bạn sẽ giảm lượng chi phí giao tiếp, do đó cải thiện hiệu suất.

  • Trình điều khiển JDBC không bắt buộc phải hỗ trợ tính năng này. Bạn nên sử dụng phương thức DatabaseMetaData.supportsBatchUpdates () để xác định xem cơ sở dữ liệu đích có hỗ trợ xử lý cập nhật hàng loạt hay không. Phương thức trả về true nếu trình điều khiển JDBC của bạn hỗ trợ tính năng này.

  • Các addBatch()Phương thức Statement, PreparedStatementCallableStatement được sử dụng để thêm các câu lệnh riêng lẻ vào lô. CácexecuteBatch() được sử dụng để bắt đầu thực hiện tất cả các câu lệnh được nhóm lại với nhau.

  • Các executeBatch() trả về một mảng các số nguyên và mỗi phần tử của mảng biểu thị số lượng cập nhật cho câu lệnh cập nhật tương ứng.

  • Cũng như bạn có thể thêm các câu lệnh vào một lô để xử lý, bạn có thể xóa chúng bằng clearBatch()phương pháp. Phương thức này loại bỏ tất cả các câu lệnh bạn đã thêm bằng phương thức addBatch (). Tuy nhiên, bạn không thể chọn câu lệnh nào để loại bỏ một cách có chọn lọc.

JDBC - Dữ liệu truyền trực tuyến:

Đối tượng PreparedStatement có khả năng sử dụng các luồng đầu vào và đầu ra để cung cấp dữ liệu tham số. Điều này cho phép bạn đặt toàn bộ tệp vào các cột cơ sở dữ liệu có thể chứa các giá trị lớn, chẳng hạn như kiểu dữ liệu CLOB và BLOB.

Có thể sử dụng các phương pháp sau để truyền dữ liệu:

  • setAsciiStream(): Phương pháp này được sử dụng để cung cấp các giá trị ASCII lớn.

  • setCharacterStream(): Phương pháp này được sử dụng để cung cấp các giá trị UNICODE lớn.

  • setBinaryStream(): Phương pháp này được sử dụng để cung cấp các giá trị nhị phân lớn.

Phương thức setXXXStream () yêu cầu một tham số bổ sung, kích thước tệp, bên cạnh trình giữ chỗ tham số. Tham số này thông báo cho trình điều khiển bao nhiêu dữ liệu sẽ được gửi đến cơ sở dữ liệu bằng cách sử dụng luồng.

Để biết chi tiết về tất cả các khái niệm này, bạn cần xem qua hướng dẫn đầy đủ.