Bài đăng nổi bật


2.  More JDBC

2.1  Example 4: Atomic Transaction (Commit and Rollback)

Một giao dịch nguyên tử - Atomic Transaction là một nhóm các câu lệnh SQL, tất cả đều thành công hoặc không thành công. Điều này là để ngăn chặn cập nhật một phần vào cơ sở dữ liệu. Để quản lý giao dịch trong JDBC, trước tiên chúng tôi vô hiệu hóa commit tự động mặc định (commit mọi câu lệnh SQL), đưa ra một vài câu lệnh SQL và sau đó quyết định có đưa ra một commit()cam kết thay đổi hay rollback()loại bỏ tất cả các thay đổi kể từ lần xác nhận cuối cùng . Ví dụ:
// Step 3 & 4: Execute queries and process the query results
// Disable auto-commit for the connection, which commits every SQL statement.
conn.setAutoCommit(false);

// Before Changes
ResultSet rset = stmt.executeQuery("select id, qty from books where id in (1001, 1002)");
System.out.println("-- Before UPDATE --");
while(rset.next()) {
   System.out.println(rset.getInt("id") + ", " + rset.getInt("qty"));
}
conn.commit();     // Commit SELECT
 
// Issue two UPDATE statements thru executeUpdate()
stmt.executeUpdate("update books set qty = qty + 1 where id = 1001");
stmt.executeUpdate("update books set qty = qty + 1 where id = 1002");
conn.commit();     // Commit UPDATEs
 
rset = stmt.executeQuery("select id, qty from books where id in (1001, 1002)");
System.out.println("-- After UPDATE and Commit --");
while(rset.next()) {
   System.out.println(rset.getInt("id") + ", " + rset.getInt("qty"));
}
conn.commit();     // Commit SELECT
 
// Issue two UPDATE statements thru executeUpdate()
stmt.executeUpdate("update books set qty = qty - 99 where id = 1001");
stmt.executeUpdate("update books set qty = qty - 99 where id = 1002");
conn.rollback();   // Discard all changes since the last commit
 
rset = stmt.executeQuery("select id, qty from books where id in (1001, 1002)");
System.out.println("-- After UPDATE and Rollback --");
while(rset.next()) {
   System.out.println(rset.getInt("id") + ", " + rset.getInt("qty"));
}
conn.commit();     // Commit SELECT
Trong một số triển khai cơ sở dữ liệu, bạn cũng được yêu cầu "commit" câu lệnh SELECT statement như vậy. 
Rolling Back in Catch-Clause
Các method rollback()thường được gọi bất cứ khi nào có một lỗi (ví dụ SQLException). Do đó, nó nên được đặt trong phần catchVí dụ,
import java.sql.*;
 
public class JdbcCommitCatchTest {  // JDK 7 and above
   public static void main(String[] args) throws SQLException {
      try (
         Connection conn = DriverManager.getConnection(
               "jdbc:mysql://localhost:8888/ebookshop", "myuser", "xxxx"); // MySQL
         Statement stmt = conn.createStatement();
      ) {
         try {
            // Disable auto-commit
            conn.setAutoCommit(false);
 
            // Issue two INSERT statements
            stmt.executeUpdate("insert into books values (4001, 'Paul Chan', 'Mahjong 101', 4.4, 4)");
            // Duplicate primary key, which triggers a SQLException
            stmt.executeUpdate("insert into books values (4001, 'Peter Chan', 'Mahjong 102', 4.4, 4)");
            conn.commit();     // Commit changes only if all statements succeed.
 
         } catch(SQLException ex) {
            System.out.println("-- Rolling back changes --");
            conn.rollback();   // Rollback to the last commit.
            ex.printStackTrace();
         }
      }
   }
}
Ghi chú:
  1. Trong JDK 7 try-with-resource syntax, bạn không thể truy cập được các tài nguyên đã khai báo trong try (in try) trong mệnh đề catch-clause, e.g. để thực hiện conn.rollback(). (Test it out yourself!) Do đó, chúng ta cần lồng 1 try-catch nữa ở phía dưới try-with-resource để thực hiện conn.rollback(), điều này khá lộn xộn nhờ =)) ... nhưng là một sự-lộn-xộn-cần-thiết :D để đảm bảo tối ưu hóa tài nguyên và xử lý lỗi tuyệt đối :D 
  2. Bạn sẽ nhận được một ngoại lệ về "duplicate entry on primary key", ví dụ: trong MySQL:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '4001' for key 'PRIMARY'

2.2  Example 5: ResultSetMetaData

Mỗi đối tượng ResultSet được liên kết với một tiêu đề (được gọi meta-data), chứa thông tin về ResultSet đối tượng, chẳng hạn như số cột, tên và loại cột, v.v. Dữ liệu meta được lưu trữ trong một  đối tượng ResultSetMetaDataBạn có thể sử dụng phương thức rset.getMetaData()để truy xuất đối tượng siêu dữ liệu liên quan của ResultSet rset.
ResultSetMetaData là hữu ích trong việc xử lý động ResultSetBạn có thể truy xuất số lượng cột và sử dụng để truy xuất nội dung của một số cột cụ thể trong hàng hiện tại. Lưu ý rằng số cột bắt đầu từ 1 (không phải 0)Ví dụ, rset.getXxx(columnNumber)
// Step 3 & 4: Execute query and process query result
ResultSet rset = stmt.executeQuery("select * from books");
// Get the metadata of the ResultSet
ResultSetMetaData rsetMD = rset.getMetaData();
// Get the number of column from metadata
int numColumns = rsetMD.getColumnCount();
 
// Print column names - Column Index begins at 1 (instead of 0)
for (int i = 1; i <= numColumns; ++i) {
   System.out.printf("%-30s", rsetMD.getColumnName(i));
}
System.out.println();
 
// Print column class names
for (int i = 1; i <= numColumns; ++i) {
   System.out.printf("%-30s",
           "(" + rsetMD.getColumnClassName(i) + ")");
}
System.out.println();
 
// Print column contents for all the rows
while (rset.next()) {
   for (int i = 1; i <= numColumns; ++i) {
      // getString() can be used for all column types
      System.out.printf("%-30s", rset.getString(i));
   }
   System.out.println();
}
Output 


Exercise 1: Nâng cấp View ebookStore. (nên backup sourcode trước nha). 

Phần ebookstore bạn đã có những phần Hiển thị dữ liệu (danh sách sách, khách hàng, hoá đơn ...). Hãy tìm lại những đoạn select đó, và nâng cấp phần hiển thị sang dạng hàng và cột như ví dụ trên, để thêm đẹp nội dung và rõ thông tin. 

2.3  Example 6: DatabaseMetaData

[TODO]

2.4  Example 7: PreparedStatement

JDBC cung cấp một lớp được gọi PreparedStatement, cho phép bạn truyền tham số vào câu lệnh SQL và thực thi cùng một câu lệnh SQL nhiều lần. Lệnh PreparedStatement là một câu lệnh SQL được biên dịch trước có hiệu quả hơn so với việc sử dụng Statement nhiều lần. Trong một PreparedStatement'?'biểu thị một người giữ chỗ cho tham số. Một tập hợp các phương thức có thể được sử dụng để điền vào các tham số. Ví dụ,setXxx(placeHolderNumbervalue)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.sql.*;             // Use classes in java.sql package
 
public class JdbcPreparedStatementTest {  // JDK 7 and above
   public static void main(String[] args) {
      try (
         Connection conn = DriverManager.getConnection(
               "jdbc:mysql://localhost:8888/ebookshop", "myuser", "xxxx"); // MySQL
 
         // Two PreparedStatements, one for INSERT and one for SELECT
         PreparedStatement pstmt = conn.prepareStatement(
             "insert into books values (?, ?, ?, ?, ?)");  // Five parameters 1 to 5
         PreparedStatement pstmtSelect = conn.prepareStatement("select * from books");
      ) {
         pstmt.setInt(1, 7001);  // Set values for parameters 1 to 5
         pstmt.setString(2, "Mahjong 101");
         pstmt.setString(3, "Kumar");
         pstmt.setDouble(4, 88.88);
         pstmt.setInt(5, 88);
         int rowsInserted = pstmt.executeUpdate();  // Execute statement
         System.out.println(rowsInserted + "rows affected.");
 
         pstmt.setInt(1, 7002);  // Change values for parameters 1 and 2
         pstmt.setString(2, "Mahjong 102");
         // No change in values for parameters 3 to 5
         rowsInserted = pstmt.executeUpdate();
         System.out.println(rowsInserted + "rows affected.");
 
         // Issue a SELECT to check the changes
         ResultSet rset = pstmtSelect.executeQuery();
         while(rset.next()) {
            System.out.println(rset.getInt("id") + ", "
                  + rset.getString("author") + ", "
                  + rset.getString("title") + ", "
                  + rset.getDouble("price") + ", "
                  + rset.getInt("qty"));
         }
      } catch(SQLException ex) {
         ex.printStackTrace();
      }
      // Step 5: Close the resources - Done automatically by try-with-resources
   }
}
Trong ví dụ này, chúng tôi đã sử dụng hai PreparedStatements: một cho INSERT 5 tham số, ký hiệu là '?'một số khác SELECT không có tham số - nhưng bạn có thể sử dụng lại SELECT hiệu quả hơn.
Khi một tham số đã được xác định cho một lần cho trước PreparedStatement, nó có thể được sử dụng cho nhiều lần thực thi, cho đến khi nó bị xóa bởi một lệnh gọi đến pstmt.clearParameter()Trong ví dụ trên, các tham số thứ 3, 4 và 5 của thứ 2 PreparedStatementđược đặt trong 1 PreparedStatement.
Exercise: [TODO]

2.5  Example 8: Batch Processing

JDBC 2.0 (có sẵn trong JDK 1.2) hỗ trợ xử lý hàng loạt các câu lệnh SQL, để cải thiện hiệu suất. Mỗi câu lệnh được thêm vào lô thông qua Statement.addBatch()hoặc PreparedStatement.addBatch()Toàn bộ lô câu lệnh sau đó được gửi đến cơ sở dữ liệu để thực thi thông qua executeBatch(), nó trả về một int mảng giữ mã trả về của mỗi câu lệnh.
// Step 3 & 4: Execute query and Process the query result
conn.setAutoCommit(false);  // Turn off auto-commit for each SQL statement
 
stmt.addBatch("insert into books values (8001, 'Java ABC', 'Kevin Jones', 1.1, 99)");
stmt.addBatch("insert into books values (8002, 'Java XYZ', 'Kevin Jones', 1.1, 99)");
stmt.addBatch("update books set price = 11.11 where id=8001 or id=8002");
int[] returnCodes = stmt.executeBatch();
 
System.out.print("Return codes are: ");
for (int code : returnCodes) {
   System.out.printf(code + ", ");
}
System.out.println();
 
conn.commit();  // Commit SQL statements
Bạn cũng có thể sử dụng PreparedStatement để xử lý hàng loạt:
// Step 1: Allocate a "Connection"
Connection conn = DriverManager.getConnection(......);
 
// Step 2: Allocate a "PreparedStatement" instead of "Statement"
PreparedStatement pstmt = conn.prepareStatement(
   "insert into books values (?, ?, ?, ?, ?)");  // Five parameters 1 to 5
 
conn.setAutoCommit(false);  // Disable auto-commit for each SQL statement
 
pstmt.setInt(1, 8003);  // Set values for parameters 1 to 5
pstmt.setString(2, "Java 123");
pstmt.setString(3, "Kevin Jones");
pstmt.setDouble(4, 12.34);
pstmt.setInt(5, 88);
pstmt.addBatch();   // add the statement for batch processing
 
pstmt.setInt(1, 8004);  // Change values for parameters 1 and 2
pstmt.setString(2, "Java 456");
// No change in values for parameters 3 to 5
pstmt.addBatch();  // add the statement for batch processing
 
int[] returnCodes = pstmt.executeBatch();
  // executeBatch() returns an int array, keeping the return codes of all statements

System.out.print("Return codes are: ");
for (int code : returnCodes) System.out.printf(code + ", ");
System.out.println();
 
conn.commit();
Exercise 2: Nâng Cấp Performance eBookStore
Bạn cũng hãy sử dụng PreparedStatement để xử lý việc thao tác với dữ liệu thay thế Statement trong phiên bản cũ. 

Post a Comment

Mới hơn Cũ hơn