Bài giảng Lập trình Java - Chương 3: Lập trình Java kết nối với CSDL bằng JDBC

JAVA DATABASE CONNECTIVITY

Giới thiệu JDBC

Một số Class và Interface của JDBC API thường dùng

Các bước thực hiện truy cập CSDL sử dụng JDBC

Bước 1: Đăng ký driver

Bước 2: Tạo đối tượng kết nối đến CSDL

Bước 3: Tạo đối tượng để thực hiện các lệnh thao tác lên CSDL & Xây dựng câu lệnh tương ứng (đọc,thêm, xóa, sửa).

Bước 4: Thực hiện lệnh

Bước 5: Xử lý kết quả trả về (optional)

Bước 6: Đóng kết nối

ExecuteBath / Xử lý lỗi và ngoại lệ / Transaction

Store Procedure

 

pptx 43 trang phuongnguyen 5160
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lập trình Java - Chương 3: Lập trình Java kết nối với CSDL bằng JDBC", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng Lập trình Java - Chương 3: Lập trình Java kết nối với CSDL bằng JDBC

Bài giảng Lập trình Java - Chương 3: Lập trình Java kết nối với CSDL bằng JDBC
 Chương 3 :  Lập trình Java kết nối với CSDL bằng JDBC 
J AVA D ATA B ASE C ONNECTIVITY 
Giới thiệu JDBC 
Một số Class và Interface của JDBC API thường dùng 
Các bước thực hiện truy cập CSDL sử dụng JDBC 
Bước 1 : Đăng ký driver 
Bước 2 : Tạo đối tượng kết nối đến CSDL 
Bước 3 : Tạo đối tượng để thực hiện các lệnh thao tác lên CSDL & Xây dựng câu lệnh tương ứng (đọc,thêm, xóa, sửa). 
Bước 4 : Thực hiện lệnh 
Bước 5 : Xử lý kết quả trả về (optional) 
Bước 6 : Đóng kết nối 
ExecuteBath / Xử lý lỗi và ngoại lệ / Transaction 
Store Procedure 
JDBC 
JDBC ( J ava D ata b ase C onnectivity) cung cấp cho java developer tập các interface chuẩn dùng để truy xuất dữ liệu quan hệ. 
JDBC được phát triển bởi JavaSoft. 
Kiến trúc JDBC 
Khi làm việc với JDBC, java developer sẽ làm việc như nhau đối với các hệ cơ sở dữ liệu khác nhau. 
Java developer không phụ thuộc vào một hệ cơ sở dữ liệu cụ thể nào. 
Java developer không cần phải quan tâm đến sự khác nhau khi giao tiếp với các HQTCSDL khác nhau. 
Kiến trúc JDBC 
Kiến trúc JDBC 
Hoạt động của JDBC 
JDBC API 
Class và Interface của JDBC API thuộc gói java.sql 
DriverManager dùng để nạp các driver và tạo Connection đến cơ sở dữ liệu. 
Driver : Driver của cơ sở dữ liệu, mỗi JDBC Driver đều cài đặt lại Interface này. 
Connection :Thiết lập một Connection đến cơ sở dữ liệu và cho phép tạo các Statement . 
Statement : Gắn kết với một connection đến cơ sở dữ liệu và cho phép thực thi các câu lệnh SQL. 
CallableStatement tương tự Statement nhưng áp dụng cho Store procedures. 
JDBC API 
PreparedStatement : Tương tự như Statement nhưng áp dụng cho Precompiled SQL. 
ResultSet : Cung cấp thông tin rút trích từ cơ sở dữ liệu , cho phép truy xuất các dòng dữ liệu. 
ResultSetMetaData : Cung cấp các thông tin như kiểu dữ liệu và các thuộc tính trong Resultset. 
DatabaseMetaData : Cung cấp các thông tin của cơ sở dữ liệu kết nối. 
SQLException : Cung cấp thông tin các ngoại lệ xảy ra khi tương tác với cơ sở dữ liệu. 
JDBC API 
Một số bước kỹ thuật cơ bản sử dụng JDBC 
Bước 1 : Đăng ký driver 
Bước 2 : Tạo đối tượng kết nối đến CSDL 
Bước 3 : Tạo đối tượng để thực hiện các lệnh thao tác lên CSDL & Xây dựng câu lệnh tương ứng (đọc,thêm, xóa, sửa). 
Bước 4 : Thực hiện lệnh 
Bước 5 : Xử lý kết quả trả về (optional) 
Bước 6 : Đóng kết nối 
Bước 1 : Đăng ký driver JDBC 
Chuẩn bị driver tương ứng với HQTCSDL & thực hiện đăng ký. 
Đăng ký driver MySQL: 
Chuẩn bị driver: download mysql-connector-java-5.1.22.zip 
Đăng ký: 
Cách 1: Sử dụng Class.forName 
Class.forName(" org.gjt.mm.mysql "); 
Cách 2: DriverManager.registerDriver 
Driver driver = new org.gjt.mm.mysql .Driver(); 
DriverManager. registerDriver ( driver ); 
Các package cần sử dụng: 
import java.sql.Connection; 
import java.sql.Driver; 
import java.sql.DriverManager; 
Bước 2 : Tạo & mở kết nối đến CSDL 
CSDL minh họa: 
Name: NhanVienDB 
MySQL DBMS: 
Username: root 
Password: root 
Port: 3306 
Domain: localhost 
MAPHG: AUTO INCREMENT 
Bước 2 : Tạo & mở kết nối đến CSDL 
Sử dụng phương thức getConnection của DriverManager 
Một số cú pháp: 
Connection getConnection (String url ); 
Connection getConnection (String url , String user , String password ); 
Connection getConnection (String url , java.util.Properties info ); 
Bước 2 : Tạo & mở kết nối đến CSDL 
Java Application 
JDBC 
MySQL DBMS 
NhanVienDB 
URL: jdbc:mysql :// localhost : 3306 / NhanVienDB 
Username: root 
Password: root 
MySQL JDBC Driver 
Port: 3306 
Domain: localhost 
Username: root 
Password: root 
Bước 1 & 2 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
package demojdbc; 
import java.sql.*; 
import java.util.Properties; 
public class DemoJDBC { 
 public static void main(String [] args){ 
 //1. Đăng ký driver và tạo kết nối đến CSDL 
 Driver driver = new org.gjt.mm.mysql.Driver(); 
 DriverManager.registerDriver(driver); 
 //2. Tạo kết nối đến CSDL 
 String conString = " jdbc:mysql :// localhost : 3306 / NhanVienDB "; 
 Properties info = new Properties(); 
 info.setProperty("characterEncoding", "utf8"); 
 info.setProperty("user", "root"); 
 info.setProperty("password", ""); 
 Connection connection; 
 connection = DriverManager.getConnection(conString, info); 
 //3. Tạo đối tượng Statement để thực hiện thao tác dữ liệu mong muốn 
 } 
} 
1 
2 
Bước 3 : Tạo đối tượng để thực thi và chuẩn bị các lệnh SQL 
Sử dụng phương thức createStatement () của đối tượng kết nối: 
Chuẩn bị các lệnh SQL: 
SELECT : Truy vấn dữ liệu từ bảng 
DELETE : Xóa dữ liệu từ bảng 
UPDATE : Cập nhật dữ liệu vào bảng 
INSERT : Thêm dữ liệu vào bảng 
Ví dụ: 
Statement statement = connection. createStatement (); 
String sql = " SELECT * FROM NHANVIEN "; 
Query (Đọc) 
Update (Thay đổi) 
Bước 3 : Tạo đối tượng để thực thi và chuẩn bị các lệnh SQL 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
package demojdbc; 
import java.sql.*; 
import java.util.Properties; 
public class DemoJDBC { 
 public static void main(String [] args){ 
 //1. Đăng ký driver và tạo kết nối đến CSDL 
 //2. Tạo kết nối đến CSDL 
 //3. Tạo đối tượng Statement để thực hiện thao tác dữ liệu mong muốn 
 Statement statement = connection.createStatement(); 
 String sql = "SELECT * FROM NHANVIEN"; 
 //4. Thực hiện lệnh SQL 
 //5. Xử lý kết quả trả về 
 } 
} 
3 
Bước 4 : Thực thi SQL 
Sử dụng một số cú pháp: 
//Thực thi câu truy vấn (SELECT). Kết quả trả về là một tập dữ liệu ResultSet 
ResultSet statement. executeQuery ( String sql) 
//Thực thi câu lệnh cập nhật dữ liệu (Thêm, xóa, sửa) 
int statement. executeUpdate ( String sql) 
//Thực thi câu lệnh SQL nói chung (thêm, xóa, sửa, truy vấn, ) 
boolean statement. execute ( String sql) 
Bước 4 : Thực thi SQL 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
package demojdbc; 
import java.sql.*; 
import java.util.Properties; 
public class DemoJDBC { 
 public static void main(String [] args){ 
 //1. Đăng ký driver và tạo kết nối đến CSDL 
 //2. Tạo kết nối đến CSDL 
 //3. Tạo đối tượng Statement để thực hiện thao tác dữ liệu mong muốn 
 Statement statement = connection.createStatement(); 
 String sql = "SELECT * FROM NHANVIEN"; 
 //4. Thực hiện truy xuất (đọc / ghi) 
 ResultSet rs = statement.executeQuery(sql); 
 //5. Xử lý kết quả trả về 
 } 
} 
4 
Bước 5: Xử lý kết quả trả về 
Tùy vào kết quả trả về của việc thực thi câu lệnh: 
ResultSet statement. executeQuery ( String sql) 
🡪 Kết quả trả về là một tập dữ liệu của câu truy vấn: Cần duyệt qua tập dữ liệu này để xử lý (hiển thị, ) 
int statement. executeUpdate ( String sql) 
🡪 Kết quả trả về là số dòng bị ảnh hưởng của việc thêm, xóa, sửa. 
boolean statement. execute ( String sql) 
🡪Tùy vào câu lệnh SQL sẽ có cách thức xử lý tương ứng 
5a. Lấy dữ liệu từ ResultSet 
Lấy kết quả từ câu truy vấn: 
Sử dụng . next() để đến dòng kế tiếp. 
ResultSet rs = statement. executeQuery (sql); 
while ( rs.next() ) { 
int c1= rs. getInt ( " Column1 "); 
String c2 = rs. getString ( " Column2 "); 
} 
Column1 
Column2 
Column3 
ResultSet rs = statement. executeQuery (sql) 
Hoặc 
statement. execute (sql) 
ResultSet rs = statement. getResultSet () 
rs.next() 
ResultSet 
5a. Lấy dữ liệu từ bảng PHONGBAN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
 Statement statement = connection.createStatement(); 
 String sql = "SELECT * FROM PHONGBAN" ; 
 ResultSet rs = statement. executeQuery (sql); 
 while (rs.next()){ 
 int manv= rs.getInt( "MAPHG" ); 
 String hoten = rs.getString( "TENPHG" ); 
 System. out .print(manv+ " " ); 
 System. out .println(hoten); 
 } 
 connection.close(); 
5 
5a. Lấy dữ liệu từ bảng NHANVIEN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
 Statement statement = connection.createStatement(); 
 String sql = “select * from NHANVIEN Where PHONG = 1" ; 
 statement. execute (sql); 
 ResultSet rs = statement.getResultSet(); 
 while (rs.next()){ 
 int manv = rs.getString( "MANV" ); 
 String hoten = rs.getString( "HOTEN" ); 
 Date ngaysinh = rs.getDate( "NGAYSINH" ); 
 float luong = rs.getFloat( "LUONG" ); 
 System. out .println(  ); 
 } 
 connection.close(); 
5 
5b. Xóa dữ liệu bảng PHONGBAN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 Statement statement = connection.createStatement(); 
 String sql = " delete from PHONGBAN where MAPHG = 1 " ; 
 int n = statement. executeUpdate (sql); 
 if (n == 1){ 
System. out .println( “Xóa thành công !!!" ); 
 } else { 
System. out .println( "Lỗi !!!" ); 
 } 
 connection.close(); 
5 
5b. Xóa dữ liệu bảng NHANVIEN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 Statement statement = connection.createStatement(); 
 String sql = "delete from NHANVIEN where MAPHG = 1" ; 
 int n = statement. executeUpdate (sql); 
 if (n > = 1){ 
System. out .println( “Xóa thành công !!!" ); 
 } else { 
System. out .println( "Lỗi !!!" ); 
 } 
 connection.close(); 
5 
5b. Sửa dữ liệu bảng PHONGBAN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
 Statement statement = connection.createStatement(); 
 String sql = String.format ( "update PHONGBAN 
 set TENPHONG = ' %s ' 
 where MAPHG = %d " , tenphong, maphong) ; 
 int n = statement. executeUpdate (sql); 
 if (n == 1){ 
System. out .println( “Xóa thành công !!!" ); 
 } else { 
System. out .println( "Lỗi !!!" ); 
 } 
 connection.close(); 
5 
5b. Sửa dữ liệu bảng NHANVIEN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
 Statement statement = connection.createStatement(); 
 String sql = String.format( "update NHANVIEN 
 set HOTEN= ' %s ' , 
 PHAI = ' %s ', 
 LUONG= %f 
 where MANV = %d " , hoten, phai, luong, manv) ; 
 int n = statement. executeUpdate (sql); 
 if (n == 1){ 
System. out .println( “Xóa thành công !!!" ); 
 } else { 
System. out .println( "Lỗi !!!" ); 
 } 
 connection.close(); 
5 
5b. Thêm dữ liệu bảng NHANVIEN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
 String manv =  
 String hoten =  
 float luong =  
 Statement statement = connection.createStatement(); 
 String sql = String.format ( "INSERT INTO NHANVIEN (MANV, HOTEN, LUONG, ) VALUES (' %s ' , ' %s ', %f , )" , manv, hoten, luong,  ) 
 int n = statement. executeUpdate (sql); 
 if (n == 1){ 
System. out .println( " Thêm thành công !!!" ); 
 } else { 
System. out .println( "Lỗi !!!" ); 
 } 
 connection.close(); 
... 
5 
5b. Thêm dữ liệu bảng PHONGBAN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
 String tenphong =  
 Statement statement = connection.createStatement(); 
 String sql = String.format ( "INSERT INTO PHONGBAN (TENPHONG) VALUES ('%s' ", tenphong ) 
 int n = statement. executeUpdate (sql, Statement. RETURN_GENERATED_KEYS ); 
 if (n > 0){ 
System. out .println( " Thêm thành công !!!" ); 
ResultSet rs=statement. getGeneratedKeys (); 
 if(rs.next()){ 
 int maDanhMuc = rs.getInt( 1 ); 
 System.out.println( "Mã danh mục vừa thêm: " +maDanhMuc); 
 } 
 } else { 
System. out .println( "Lỗi !!!" ); 
 } 
 connection.close(); 
... 
Khóa tự động tăng 
5 
5b. Thêm dữ liệu bảng PHONGBAN 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
 Statement statement = connection. createStatement (); 
 String[] arrPhong = {“ PB1 ", “ PB2 ", " PB3 "}; 
 String sql = " INSERT INTO PHONGBAN (TENPHG) VALUES "; 
 for (int i=0; i < arrPhong.length; i++){ 
 sql = sql + String.format(" ('%s') ", arrPhong[i]); 
 if( i < arrPhong. length -1) { sql = sql + ", "; } 
 } 
 int n = statement. executeUpdate (sql, Statement. RETURN_GENERATED_KEYS ); 
 if (n > 0) { 
 System.out.println("Thêm thành công !!!"); 
 ResultSet rs = statement. getGeneratedKeys (); 
 while (rs. next ()){ 
 int maphong = rs.getInt(1); 
 System.out.println(" Mã phòng ban vừa thêm: " + maphong); 
 } 
 } 
 connection.close(); 
Khóa tự động tăng 
sql : INSERT INTO PHONGBAN (TENPHG) VALUES ('PB1'), ('PB2'), ('PB3') 
5 
6. Đóng kết nối 
Sử dụng .close() của đối tượng Connection 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
package demojdbc; 
import java.sql.*; 
import java.util.Properties; 
public class DemoJDBC { 
 public static void main(String[] args){ 
 //1. Đăng ký driver và tạo kết nối đến CSDL 
 //2. Tạo kết nối đến CSDL 
 //6. Đóng kết nối 
 connection.close(); 
 } 
} 
6 
executeBatch 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
. . . 
String sql1= "INSERT INTO DANHMUC(TENDANHMUC) VALUES('Java')" ; 
String sql2= "INSERT INTO DANHMUC(TENDANHMUC) VALUES('PHP')" ; 
String sql3=" UPDATE DANHMUC SET TENDANHMUC='C' WHERE 
MADANHMUC=43 "; 
Statement statement=connection.createStatement(); 
statement.addBatch(sql1); 
statement.addBatch(sql2); 
statement.addBatch(sql3); 
int [] arrResult = statement. executeBatch (); 
. . . 
arrResult [ i ] : Số dòng bị ảnh hưởng của câu lệnh SQL thứ i 
Xử lý ngoại lệ 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
package demojdbc; 
import java.sql.*; 
import java.util.Properties; 
public class DemoJDBC { 
 public static void main(String[] args){ 
 try { 
 //1. Đăng ký driver và tạo kết nối đến CSDL 
 //2. Tạo kết nối đến CSDL 
 //6. Đóng kết nối 
 } catch (SQLException ex) { 
 System.out.println(ex); 
 } 
 } 
} 
PreparedStatement 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
public static void main(String[] args){ 
 try { 
 String sql = "INSERT INTO T(X, Y) VALUES ( ? , ? )"; 
 PreparedStatement statement = connection. prepareStatement (sql, Statement. RETURN_GENERATED_KEYS ); 
 statement.setString( 1 , "Value Of X"); 
 statement.setString( 2 , "Value Of Y"); 
 int n = statement.executeUpdate(); 
 connection.close(); 
 } catch (SQLException ex) { 
 System.out.println(ex); 
 } 
 } 
Sử dụng Transaction 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
try { 
String sql1= insert/delete/update . . . 
String sql2= insert/delete/update . . . 
Connection con =DriverManager. getConnection ( cs, info); 
try{ 
con. setAutoCommit ( false ); 
Statement statement1= con. createStatement (); 
Statement statement2= con. createStatement (); 
statement1. executeUpdate (sql1); 
statement2. executeUpdate (sql2); 
con. commit (); 
}catch ( SQLException ex){ 
con. rollBack (); 
}finally{ 
con. close (); 
} 
} catch ( SQLException ex) { //Xử lý lỗi } 
Sử dụng Transaction 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
String sql1= insert/delete/update . . . 
String sql2= insert/delete/update . . . 
Connection con =DriverManager. getConnection ( cs, info); 
try{ 
con. setAutoCommit (false); 
Statement statement1= con.createStatement(); 
Statement statement2= con.createStatement(); 
statement1.executeUpdate(sql1); 
statement2.executeUpdate(sql2); 
if( điều kiện commit ){ 
con. commit (); 
}else{ 
con. rollBack (); 
} 
}catch (SQLException ex){ 
//Xử lý lỗi 
}finally{ con.close(); } 
Sử dụng Transaction 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
String sql1= insert/delete/update . . . 
String sql2= insert/delete/update . . . 
Connection con =DriverManager.getConnection( cs, info); 
try{ 
con. setAutoCommit (false); 
Statement statement1= con.createStatement(); 
Statement statement2= con.createStatement(); 
Savepoint save1 = con. setSavepoint (); 
statement1. executeUpdate (sql1); 
statement2. executeUpdate (sql2); 
if( điều kiện commit ){ 
con. commit (); 
}else{ 
con. rollBack ( save1 ); 
} 
}catch (SQLException ex){ 
//Xử lý lỗi 
}finally{ con.close();} 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
 Date ngaysinh = sdf.parse("1999-08-25"); 
 Date d = sdf.parse("2000-1-1"); 
 String sql = "INSERT INTO NHANVIEN VALUES ”; 
 Connection connection = null; 
 connection = DriverManager. getConnection (conString, info); 
 try { 
 connection. setAutoCommit (false); 
 Statement statement = connection. createStatement (); 
 statement. executeUpdate (sql); 
 if ( ngaysinh.after(d)) { 
 connection. rollback (); 
 System.out.println("NGAYSINH MUST BE BEFORE 1/1/2000"); 
 } else { 
 connection. commit (); 
 } 
 } catch (SQLException ex) { 
 System.out.println(ex); 
 } finally {connection.close();} 
Sử dụng Transaction 
CallableStatement - Xử lý Store Procedure 
1 
2 
3 
4 
5 
6 
7 
DELIMITER $$ 
CREATE PROCEDURE spThemDanhMuc ( 
in tenDanhMuc VARCHAR (45)) 
BEGIN 
INSERT INTO DANHMUC(TENDANHMUC) VALUES (tenDanhMuc); 
SELECT LAST_INSERT_ID (); 
END 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
String tenDanhMuc = "C++"; 
CallableStatement statement = 
connection.prepareCall(" { call spThemDanhMuc( ? )} "); 
statement.setString( 1 , tenDanhMuc); 
statement.execute(); 
ResultSet rs = statement.getResultSet(); 
if (rs.next()) { 
int maDanhMuc = rs.getInt( 1 ); 
System.out.println(maDanhMuc); 
} 
CallableStatement - Xử lý Store Procedure 
CallableStatement - Xử lý Store Procedure 
1 
2 
3 
4 
5 
6 
7 
8 
DELIMITER $$ 
CREATE PROCEDURE spThemDanhMuc ( 
in tenDanhMuc VARCHAR (45), 
out maDanhMuc int ) 
BEGIN 
INSERT INTO DANHMUC(TENDANHMUC) VALUES (tenDanhMuc); 
SET maDanhMuc = LAST_INSERT_ID (); 
END 
1 
2 
3 
4 
5 
6 
7 
8 
String tenDanhMuc = "C++"; 
CallableStatement statement = 
connection. prepareCall (" {call spThemDanhMuc ( ? , ? ) } "); 
statement. setString ( 1 , tenDanhMuc); 
statement. registerOutParameter ( 2 ,Types.INTEGER); 
statement. execute (); 
int maDanhMuc = statement. getInt ( 2 ); 
System.out. println (maDanhMuc); 
MySQL 
Cài đặt MySQL server 
WAMP 
IDE: 
phpMyAdmin (tích hợp sẵn trong WAMP) 
MySQL Workbench 5.2 CE 

File đính kèm:

  • pptxbai_giang_lap_trinh_java_chuong_3_lap_trinh_java_ket_noi_voi.pptx