Java JDBC API
- 29-11-2023
- Toanngo92
- 0 Comments
Mục lục
Khái niệm JDBC
Một cơ sở dữ liệu chứa dữ liệu theo cách tổ chức. Ứng dụng client/server sử dụng rộng rãi lập trình cơ sở dữ liệu. Các hoạt động điển hình liên quan đến ứng dụng cơ sở dữ liệu bao gồm việc mở kết nối, truyền thông với cơ sở dữ liệu, thực thi các câu lệnh Truy vấn Cấu trúc (SQL), và trả kết quả truy vấn.
Java đã khẳng định vị thế của mình như một trong những nền tảng cơ bản của máy tính doanh nghiệp.
Lõi của các ứng dụng doanh nghiệp Java phụ thuộc vào Hệ thống Quản lý Cơ sở dữ liệu (DBMS), đóng vai trò là kho lưu trữ cho dữ liệu của doanh nghiệp. Do đó, để xây dựng các ứng dụng như vậy, cần truy cập vào các cơ sở dữ liệu trong kho lưu trữ. Để kết nối các ứng dụng Java với các cơ sở dữ liệu, sử dụng Giao diện Lập trình Ứng dụng (API) cho kết nối cơ sở dữ liệu. Phần mềm API này là một bộ thư viện ứng dụng và trình điều khiển cơ sở dữ liệu, việc triển khai của nó không phụ thuộc vào ngôn ngữ lập trình, hệ thống cơ sở dữ liệu và hệ điều hành.
Open DataBase Connectivity (ODBC) và Java Database Connectivity (JDBC) là hai API phổ biến được sử dụng cho những hoạt động này.
Lưu ý: JDBC không phải là từ viết tắt, mặc dù thường bị nhầm lẫn là “Java Database Connectivity”. Thực tế, đây là tên thương hiệu của sản phẩm.
Hình dưới mô tả ý tưởng hoạt động JDBC:
ODBC (Open Database Connectivity) là một API được Microsoft cung cấp để truy cập cơ sở dữ liệu. Nó sử dụng SQL làm ngôn ngữ cơ sở dữ liệu của mình. ODBC cung cấp các chức năng để chèn, sửa đổi và xóa dữ liệu cũng như lấy thông tin từ cơ sở dữ liệu.
Hình dưới mô tả kiến trúc hoạt động ODBC:
Định nghĩa về JDBC
JDBC là API dựa trên Java, cung cấp một tập hợp các lớp và giao diện được viết bằng Java để truy cập và thao tác trên các loại cơ sở dữ liệu khác nhau. JDBC API là một Java API do Sun cung cấp, nó bao gồm một tập hợp các lớp và giao diện được sử dụng để truy cập dữ liệu dạng bảng. Những lớp và giao diện này được viết bằng ngôn ngữ lập trình Java và cung cấp một API tiêu chuẩn cho các nhà phát triển cơ sở dữ liệu. Để truy cập dữ liệu một cách nhanh chóng và hiệu quả từ cơ sở dữ liệu, ứng dụng Java sử dụng JDBC. Ưu điểm của việc sử dụng JDBC API là một ứng dụng có thể truy cập bất kỳ cơ sở dữ liệu nào và chạy trên bất kỳ nền tảng nào hỗ trợ JVM. Nói cách khác, một ứng dụng Java có thể viết một chương trình sử dụng JDBC API và câu lệnh SQL có thể truy cập bất kỳ cơ sở dữ liệu nào.
Sự kết hợp giữa JDBC API và nền tảng Java mang lại lợi ích của việc truy cập bất kỳ nguồn dữ liệu nào và sự linh hoạt khi chạy trên bất kỳ nền tảng nào hỗ trợ JVM. Đối với một nhà phát triển, không cần phải viết các chương trình riêng biệt để truy cập các cơ sở dữ liệu khác nhau như SQL Server, Oracle hoặc IBM DB2. Thay vào đó, một chương trình duy nhất với triển khai JDBC có thể gửi các câu lệnh SQL hoặc các câu lệnh khác đến nguồn dữ liệu hoặc cơ sở dữ liệu phù hợp. Ba nhiệm vụ có thể thực hiện bằng cách sử dụng các trình điều khiển JDBC như sau: thiết lập kết nối với nguồn dữ liệu, gửi truy vấn và câu lệnh cập nhật đến nguồn dữ liệu và cuối cùng xử lý kết quả.
Vai trò của JDBC
JDBC giúp thiết lập kết nối với cơ sở dữ liệu. Đoạn văn sau giải thích sự cần thiết của JDBC.
- ODBC sử dụng một giao diện C. Cuộc gọi từ Java đến mã nguồn C nguyên thủy có nhiều hạn chế trong các lĩnh vực bảo mật, triển khai, độ bền và khả năng chuyển động tự động của ứng dụng. Điều này làm trở ngại việc sử dụng trình điều khiển ODBC trong ứng dụng Java.
- Việc dịch đúng từ giao diện C của ODBC sang một API Java không mong muốn. Ví dụ, Java không có con trỏ, trong khi ODBC sử dụng chúng, bao gồm con trỏ chung dễ gây lỗi ‘void *’. Nói một cách đơn giản, JDBC là ODBC được dịch sang một giao diện hướng đối tượng phù hợp với các lập trình viên Java.
- ODBC kết hợp cả tính năng đơn giản và nâng cao, và nó có các tùy chọn phức tạp ngay cả đối với các truy vấn đơn giản. JDBC có ưu thế vì nó được thiết kế để giữ mọi thứ đơn giản trong khi vẫn cho phép các khả năng nâng cao khi cần thiết.
- Một API Java như JDBC là cần thiết để kích hoạt một giải pháp ‘pure Java’. Khi sử dụng ODBC, bộ quản lý trình điều khiển ODBC và trình điều khiển cần phải được cài đặt thủ công trên mỗi máy khách. Tuy nhiên, vì trình điều khiển JDBC được viết hoàn toàn bằng Java, mã JDBC có thể cài đặt, di động và an toàn trên tất cả các nền tảng Java, từ máy tính mạng đến máy chủ chính.
- JDBC là một giao diện tiêu chuẩn cho các chương trình Java để truy cập cơ sở dữ liệu quan hệ. Do đó, có thể nói rằng JDBC API là một giao diện Java tự nhiên với các khái niệm SQL cơ bản. JDBC đã được xây dựng trên ODBC và do đó giữ lại các đặc điểm thiết kế cơ bản của ODBC. Trên thực tế, cả hai giao diện đều dựa trên Giao diện Cấp Độ Gọi SQL của X/Open (CLI).
Các Thành Phần Sản Phẩm của JDBC
Bốn thành phần sản phẩm của JDBC như sau:
- IBC API
JDBC API là một phần của nền tảng Java. Các API JDBC 4.0 được bao gồm trong hai gói, được tích hợp trong Java Standard Edition và Java Enterprise Edition. Hai gói đó là Java.sql và javax.sql. JDBC API cho phép truy cập vào cơ sở dữ liệu quan hệ từ ngôn ngữ lập trình Java. Do đó, JDBC API cho phép ứng dụng thực hiện các câu lệnh SQL, truy xuất kết quả và thực hiện thay đổi vào cơ sở dữ liệu cơ bản. - JDBC Driver Manager
Một ứng dụng Java được kết nối với một trình điều khiển JDBC bằng cách sử dụng một đối tượng của lớp DriverManager. Lớp DriverManager là nền tảng cơ bản của kiến trúc JDBC. Các nhiệm vụ được thực hiện bởi lớp DriverManager là đầu tiên định vị trình điều khiển cho một cơ sở dữ liệu cụ thể và sau đó xử lý các cuộc gọi khởi tạo cho JDBC. - Bộ Kiểm Tra JDBC
Bộ kiểm tra trình điều khiển JDBC giúp xác định rằng trình điều khiển JDBC sẽ chạy chương trình. - Cầu Nối JDBC-ODBC
Truy cập JDBC được cung cấp bằng cách sử dụng trình điều khiển ODBC.
Kiến trúc JDBC
JDBC là một phần cốt lõi của nền tảng Java và được bao gồm trong bản phân phối của JDK. Nhiệm vụ chính của các API JDBC là cho phép các nhà phát triển thực hiện các câu lệnh SQL một cách độc lập không phụ thuộc vào cơ sở dữ liệu cơ bản. Các lớp và giao diện của JDBC API được sử dụng để đại diện cho các đối tượng của kết nối cơ sở dữ liệu, câu lệnh SQL, tập kết quả, siêu dữ liệu cơ sở dữ liệu, câu lệnh Prepared, câu lệnh Callable, và nhiều thứ khác.
Để cung cấp khả năng kết nối với các cơ sở dữ liệu đa dạng, trình quản lý trình điều khiển và trình điều khiển cụ thể của cơ sở dữ liệu được sử dụng bởi JDBC API. Trình quản lý trình điều khiển đảm bảo rằng các trình điều khiển chính xác được sử dụng để truy cập cơ sở dữ liệu. Trình quản lý trình điều khiển hỗ trợ việc kết nối nhiều trình điều khiển để truy cập các nguồn dữ liệu khác nhau.
Hình dưới mô tả kiến trúc này
Ưu Điểm của JDBC
Một số ưu điểm của JDBC:
Tiếp tục sử dụng dữ liệu hiện tại
JDBC cho phép các ứng dụng doanh nghiệp tiếp tục sử dụng dữ liệu hiện tại ngay cả khi dữ liệu được lưu trữ trên các hệ thống quản lý cơ sở dữ liệu khác nhau.
Độc lập với nhà cung cấp
Sự kết hợp giữa Java API và JDBC API giúp dữ liệu có thể chuyển đổi từ một nhà cung cấp sang nhà cung cấp khác mà không cần sửa đổi mã ứng dụng.
Độc lập với nền tảng
JDBC thường được sử dụng để kết nối một ứng dụng người dùng với một cơ sở dữ liệu ‘ở phía sau’, không phụ thuộc vào phần mềm quản lý cơ sở dữ liệu nào đang được sử dụng để kiểm soát cơ sở dữ liệu. Theo cách này, JDBC là độc lập với nền tảng hoặc độc lập với hệ điều hành.
Dễ sử dụng
Với JDBC, sự phức tạp của việc kết nối một chương trình người dùng với một cơ sở dữ liệu ‘ở phía sau’ được giấu kín, làm cho việc triển khai dễ dàng và kinh tế để duy trì.
Mô Hình Xử Lý Dữ Liệu Hai Tầng
Mô hình xử lý dữ liệu cho việc truy cập cơ sở dữ liệu. Trong một hệ thống hai tầng, JDBC API hỗ trợ cả hai mô hình hai tầng và ba tầng. Trong một hệ thống hai tầng client/server, máy khách truyền thông trực tiếp với máy chủ cơ sở dữ liệu mà không cần sự trợ giúp của bất kỳ công nghệ trung gian nào hoặc một máy chủ khác. Trong môi trường hai tầng của JDBC, ứng dụng Java là máy khách và Hệ quản trị cơ sở dữ liệu (DBMS) là máy chủ cơ sở dữ liệu. Việc triển khai điển hình của mô hình hai tầng bao gồm việc sử dụng JDBC API để dịch và gửi yêu cầu từ máy khách đến cơ sở dữ liệu. Cơ sở dữ liệu có thể được đặt trên cùng một máy hoặc máy khác trong mạng. Kết quả được trả về cho máy khách thông qua JDBC API. Hình dưới mô tả mô hình xử lý dữ liệu hai tầng
Mô Hình Xử Lý Dữ Liệu Ba Tầng
Trong một mô hình ba tầng, một ‘tầng trung gian’ của các dịch vụ, một máy chủ thứ ba được sử dụng để gửi yêu cầu của máy khách đến máy chủ cơ sở dữ liệu. Tầng trung gian này giúp phân tách máy chủ cơ sở dữ liệu khỏi máy chủ Web. Sự tham gia của máy chủ thứ ba này hoặc máy chủ proxy cải thiện tính bảo mật bằng cách chuyển tất cả các yêu cầu đến máy chủ cơ sở dữ liệu thông qua máy chủ proxy. Máy chủ cơ sở dữ liệu xử lý các yêu cầu và gửi lại kết quả cho tầng trung gian (máy chủ proxy), sau đó lại gửi nó đến máy khách. Hình dưới mô tả mô hình xử lý dữ liệu ba tầng.
Lưu ý: Những ưu điểm của mô hình ba tầng so với mô hình hai tầng là nó làm đơn giản hóa và giảm chi phí triển khai ứng dụng. Nó cũng cung cấp quyền truy cập được kiểm soát và sửa đổi đối với cơ sở dữ liệu.
JDBC API
JDBC API là một bộ quy định đặc tả xác định cách cơ sở dữ liệu và các ứng dụng giao tiếp với nhau. Trung tâm của JDBC API dựa trên Java, vì vậy nó được sử dụng như là nền tảng chung để xây dựng tầng trung gian trong kiến trúc ba tầng.
Do đó, với JDBC API là một tầng trung gian, nó định nghĩa cách kết nối được mở giữa một ứng dụng và cơ sở dữ liệu; cách yêu cầu được giao tiếp đến cơ sở dữ liệu, các truy vấn SQL được thực hiện và kết quả truy vấn được trả về. JDBC đạt được những mục tiêu này thông qua một tập hợp các giao diện Java, được thực hiện riêng biệt bởi một tập hợp các lớp cho một hệ cơ sở dữ liệu cụ thể được biết đến như là trình điều khiển JDBC.
Loại Trình Điều Khiển JDBC
Trình điều khiển JDBC là cơ sở của API JDBC và chịu trách nhiệm đảm bảo rằng một ứng dụng có quyền truy cập đồng nhất và đồng bộ đến bất kỳ cơ sở dữ liệu nào. Trình điều khiển chuyển đổi yêu cầu của máy khách thành định dạng ngôn ngữ tự nhiên hiểu được của cơ sở dữ liệu và sau đó trình bày nó cho cơ sở dữ liệu. Phản hồi cũng được xử lý bởi trình điều khiển JDBC và được chuyển đổi thành định dạng Java và trình bày cho máy khách.
Bốn loại trình điều khiển và mô tả ngắn gọn về tính chất cơ bản của chúng được liệt kê trong Bảng 8.1.
Loại Trình Điều Khiển | Tên Trình Điều Khiển | Mô Tả |
---|---|---|
Type 1 | ODBC-JDBC Bridge | Chuyển đổi JDBC thành cuộc gọi ODBC |
Type 2 | Native API-Java | Chuyển đổi JDBC thành cuộc gọi cụ thể của cơ sở dữ liệu hoặc cuộc gọi ngôn ngữ tự nhiên |
Type 3 | JDBC-Net All-Java | Ánh xạ cuộc gọi JDBC thành giao thức ‘mạng’ cơ bản, mà lượt tiếp theo gọi các phương thức ngôn ngữ tự nhiên trên máy chủ |
Type 4 | Thin Driver | Gọi trực tiếp RDBMS từ máy khách |
Trình Điều Khiển JDBC Loại 1
Trình điều khiển Loại 1 là một sản phẩm cầu nối phần mềm Java, còn được biết đến là cầu nối JDBC-ODBC cộng với trình điều khiển ODBC.
Hình dưới mô tả kiến trúc trình điều khiển JDBC Loại 1:
Đặc điểm
Các trình điều khiển Loại 1 sử dụng công nghệ kết nối cầu nối cung cấp truy cập JDBC thông qua trình điều khiển ODBC. Điều này tạo ra một liên kết giữa JDBC API và ODBC API. ODBC API, trong quá trình đó, được thực hiện để có quyền truy cập thực tế vào cơ sở dữ liệu thông qua các trình điều khiển ODBC tiêu chuẩn.
Máy khách phải cài đặt thư viện ODBC nguyên bản, trình điều khiển và các tệp hỗ trợ cần thiết, và trong hầu hết các trường hợp, các mã khách cơ sở dữ liệu. Loại trình điều khiển này phù hợp cho mạng doanh nghiệp, nơi cài đặt máy khách không phải là vấn đề.
Ưu điểm
Các trình điều khiển Loại 1 được viết để cho phép truy cập vào các cơ sở dữ liệu khác nhau thông qua các trình điều khiển ODBC đã tồn tại. Trong một số trường hợp, chúng là lựa chọn duy nhất cho cơ sở dữ liệu như MS-Access hoặc Microsoft SQL.
Nhược điểm
Trình điều khiển Loại 1 không phù hợp cho các ứng dụng không hỗ trợ việc cài đặt phần mềm trên máy khách. Các thư viện ODBC nguyên bản và các mã khách cơ sở dữ liệu phải nằm trên máy chủ, điều này giảm hiệu suất.
Trình Điều Khiển JDBC Loại 2
Trình điều khiển Loại 2 còn được biết đến là trình điều khiển Native-API partly Java. Hình 8.8 hiển thị trình điều khiển JDBC Loại 2.
Đặc Điểm
Trình điều khiển Loại 2 bao gồm mã Java chuyển đổi các cuộc gọi JDBC thành các cuộc gọi trên API cơ sở dữ liệu địa phương cho Oracle, Sybase, DB2, hoặc bất kỳ loại DBMS nào khác. Điều này có nghĩa là trình điều khiển gọi các phương thức nguyên bản của các nhà cung cấp cơ sở dữ liệu cụ thể để có quyền truy cập vào cơ sở dữ liệu.
Loại trình điều khiển này cơ bản đi kèm với các nhà cung cấp cơ sở dữ liệu để giải thích các cuộc gọi JDBC đến giao diện cuộc gọi ngôn ngữ tự nhiên cụ thể của cơ sở dữ liệu, ví dụ, Oracle cung cấp trình điều khiển OCI. Trình điều khiển Loại 2 cũng yêu cầu thư viện cài đặt và cấu hình trên máy khách giống như các trình điều khiển Loại 1.
Ưu Điểm
Trình điều khiển Loại 2 mang lại hiệu suất tốt hơn so với trình điều khiển Loại 1. Trình điều khiển Loại 2 thường nhanh hơn so với trình điều khiển Loại 1 vì các cuộc gọi được chuyển đổi thành các cuộc gọi cụ thể của cơ sở dữ liệu.
Nhược Điểm
Trình điều khiển Loại 2 không hỗ trợ các ứng dụng không cho phép cài đặt phần mềm trên máy khách vì nó yêu cầu mã nguồn cơ sở dữ liệu nguyên bản được cấu hình trên máy khách. Các thư viện mã nguồn cụ thể của cơ sở dữ liệu này phải nằm trên máy chủ, làm giảm hiệu suất.
Trình Điều Khiển JDBC Loại 3
Trình điều khiển Loại 3 còn được biết đến là trình điều khiển JDBC-Net pure Java.
Đặc Điểm
Trình điều khiển Loại 3 là một trình điều khiển pure Java chuyển đổi các cuộc gọi JDBC thành một giao thức mạng độc lập với DBMS, sau đó được dịch lại thành các cuộc gọi cụ thể của cơ sở dữ liệu bởi một máy chủ tầng trung gian. Trình điều khiển này không yêu cầu cài đặt bất kỳ thư viện nguyên bản cụ thể của cơ sở dữ liệu nào trên máy khách. Các ứng dụng dựa trên web nên ưu tiên triển khai trình điều khiển Loại 3 vì trình điều khiển này có thể được triển khai qua internet mà không cần cài đặt trên máy khách.
Ưu Điểm
Trình điều khiển Loại 3 là loại linh hoạt nhất vì nó không yêu cầu bất kỳ phần mềm hoặc dịch vụ nguyên bản nào phải được cài đặt trên máy khách. Nó cung cấp một mức độ điều chỉnh cao để thay đổi và kiểm soát cơ sở dữ liệu cơ bản mà không cần sửa đổi trình điều khiển phía máy khách.
Nhược Điểm
Mã nguồn cụ thể của cơ sở dữ liệu phải được thực hiện trên máy chủ tầng trung gian. Vì nó hỗ trợ các ứng dụng dựa trên web, nó phải triển khai thêm bảo mật như việc truy cập qua tường lửa.
Trình Điều Khiển JDBC Loại 4
Trình điều khiển Loại 4 còn được biết đến là trình điều khiển Native-protocol pure Java hoặc Java to Database Protocol.
Đặc Điểm
Trình điều khiển Loại 4 là các trình điều khiển pure Java chuyển đổi các cuộc gọi JDBC thành giao thức mạng trực tiếp liên lạc với cơ sở dữ liệu. Điều này liên kết cuộc gọi của máy khách trực tiếp với máy chủ DBMS và cung cấp một giải pháp thực tế để truy cập mạng nội bộ (Intranet). Trong hầu hết các trường hợp, các trình điều khiển được cung cấp bởi các nhà cung cấp cơ sở dữ liệu. Những trình điều khiển này cũng không yêu cầu bất kỳ thư viện nguyên bản cụ thể của cơ sở dữ liệu nào phải được cấu hình trên máy khách và có thể triển khai trên Web mà không cần cài đặt máy khách, như yêu cầu cho các trình điều khiển Loại 3.
Ưu Điểm
Trình điều khiển Loại 4 giao tiếp trực tiếp với bộ máy cơ sở dữ liệu bằng cách sử dụng Java sockets, thay vì thông qua middleware hoặc một thư viện nguyên bản. Đây là lý do khiến cho những trình điều khiển này là những trình điều khiển JDBC nhanh nhất hiện có. Không cần phần mềm bổ sung như thư viện nguyên bản để cài đặt trên máy khách.
Nhược Điểm
Điểm yếu duy nhất của trình điều khiển Loại 4 là chúng đặc thù cho cơ sở dữ liệu. Do đó, nếu cơ sở dữ liệu backend thay đổi, người phát triển ứng dụng có thể cần mua và triển khai một trình điều khiển Loại 4 mới phù hợp với cơ sở dữ liệu mới.
Trình điều khiển Loại 1 hữu ích cho việc tạo mẫu và không phù hợp cho sản xuất. Trình điều khiển Loại 3 thêm vào tính bảo mật, bộ nhớ đệm và kiểm soát kết nối. Cả Loại 3 và Loại 4 không cần phải được cài đặt trước và có thể di động.
Gói java.sql
API JDBC định nghĩa một tập hợp các giao diện và lớp để giao tiếp với cơ sở dữ liệu. Chúng được chứa trong gói java.sql. API có một framework khác nhau nơi các trình điều khiển có thể được cài đặt động để truy cập các nguồn dữ liệu khác nhau. API JDBC không chỉ truyền các câu lệnh SQL đến cơ sở dữ liệu mà còn cung cấp cơ hội đọc và ghi dữ liệu từ bất kỳ nguồn dữ liệu nào với định dạng bảng.
Một số giao diện trong gói này được tóm tắt trong bảng dưới.
Giao Diện | Mô Tả |
---|---|
Connection | Được sử dụng để duy trì và giám sát phiên làm việc với cơ sở dữ liệu. Truy cập dữ liệu cũng có thể được kiểm soát bằng cơ chế khóa giao dịch. |
DatabaseMetaData | Giao diện này cung cấp thông tin về cơ sở dữ liệu như số phiên bản, tên các bảng và các chức năng được hỗ trợ. Cũng có các phương thức hỗ trợ khám phá thông tin cơ sở dữ liệu như kết nối hiện tại, bảng có sẵn, schema và catalogs. |
Driver | Giao diện này được sử dụng để tạo đối tượng Connection. |
PreparedStatement | Được sử dụng để thực thi các câu lệnh SQL đã được biên dịch trước. |
ResultSet | Giao diện này cung cấp các phương thức để lấy dữ liệu được trả về bởi câu lệnh SQL. |
ResultSetMetaData | Giao diện này được sử dụng để thu thập thông tin siêu dữ liệu liên quan đến đối tượng ResultSet cuối cùng. |
Statement | Được sử dụng để thực thi các câu lệnh SQL và lấy dữ liệu vào ResultSet. |
Một số lớp của gói được tóm tắt ở bảng dưới:
Lớp | Mô Tả |
---|---|
Date | Lớp này chứa các phương thức để thực hiện chuyển đổi giữa các định dạng ngày SOL và các định dạng ngày Java. |
DriverManager | Lớp này được sử dụng để xử lý việc tải và hủy tải trình điều khiển và thiết lập kết nối với cơ sở dữ liệu. |
DriverPropertyInfo | Các phương thức trong lớp này được sử dụng để lấy hoặc chèn các thuộc tính của trình điều khiển. |
Time | Lớp này cung cấp các hoạt động định dạng và phân tích cho giá trị thời gian. |
Exception | Ngoại lệ này được nâng cao khi một giá trị dữ liệu bị cắt bớt. |
SQLException | Ngoại lệ này cung cấp thông tin về lỗi truy cập cơ sở dữ liệu hoặc lỗi khác. |
SQLWarning | Ngoại lệ này cung cấp thông tin về cảnh báo truy cập cơ sở dữ liệu. |
BatchUpdateException | Ngoại lệ này được nâng cao khi có lỗi xảy ra trong quá trình cập nhật lô dữ liệu. |
Các Bước để Phát Triển Ứng Dụng JDBC
Quá trình truy cập cơ sở dữ liệu và xử lý các truy vấn qua JDBC liên quan đến các bước cơ bản sau:
- Thiết Lập Kết Nối Đến Cơ Sở Dữ Liệu Bước đầu tiên trong việc thiết lập kết nối đến cơ sở dữ liệu là thiết lập trình điều khiển JDBC với lớp
DriverManager
.DriverManager
là một lớp tĩnh, quản lý tập hợp các trình điều khiển JDBC có sẵn cho một ứng dụng. Nó chịu trách nhiệm quản lý tất cả các tham chiếu đến tất cả các đối tượng trình điều khiển có sẵn cho một khách hàng JDBC. Lớp này tìm kiếm trình điều khiển phù hợp và tải nó tự động. Sau khi trình điều khiển được tải, kết nối với cơ sở dữ liệu có thể được thiết lập. Định danh nguồn dữ liệu JDBC (URL) xác định một kết nối JDBC và thông báo cho quản lý trình điều khiển trình điều khiển và nguồn dữ liệu nào để sử dụng. - Tạo và Thực Thi Một Câu Lệnh SQL Sau khi kết nối được thiết lập với cơ sở dữ liệu, các câu lệnh SQL có thể được gửi đến cơ sở dữ liệu để xử lý. Câu lệnh SQL là ngôn ngữ truy vấn được chấp nhận toàn cầu để thực hiện các thao tác truy xuất, chèn, cập nhật hoặc xóa trên cơ sở dữ liệu.
- Xử Lý Kết Quả Sau khi thực hiện các câu lệnh SQL, kết quả được xử lý và trích xuất bằng cách sử dụng đối tượng
ResultSet
. - Đóng Kết Nối Đến Cơ Sở Dữ Liệu Vì kết nối cơ sở dữ liệu là một nguồn lực quan trọng và có hạn, kết nối nên được đóng bằng cách sử dụng phương thức
close
sau khi quá trình xử lý hoàn tất.
8.5.2 Thiết Lập Kết Nối
Trong các phiên bản trước của JDBC, bước đầu tiên để thiết lập kết nối đến cơ sở dữ liệu và sử dụng một trình điều khiển JDBC là tải lớp trình điều khiển bằng cách sử dụng phương thức Class.forName()
. Gọi phương thức Class.forName()
tạo một phiên bản của lớp trình điều khiển được chỉ định và đăng ký nó với lớp DriverManager
. Sau khi trình điều khiển được tải thành công, kết nối với cơ sở dữ liệu có thể được thiết lập.
Cú Pháp:
Class.forName(<protocol>)
trong đó,
protocol
là thông số đặc tả cho trình điều khiển sẽ được sử dụng.
Ví dụ:
Class.forName("com.mysql.cj.jdbc.Driver");
Dòng mã này thiết lập một kết nối với một trình điều khiển cầu nối JDBC-ODBC Loại 1. Tuy nhiên, trong các phiên bản gần đây của JDBC, điều này không còn được yêu cầu nữa. Đối với Java 8 trở đi, loại tiếp cận này không được hỗ trợ nữa. Thay vào đó, lớp DriverManager
được sử dụng để thiết lập kết nối với cơ sở dữ liệu. Điều này được thực hiện bằng cách sử dụng phương thức DriverManager.getConnection()
, kiểm tra tất cả các trình điều khiển có sẵn để xem chúng có đủ điều kiện để thiết lập kết nối hay không. Điều này cũng kiểm tra trình điều khiển nhận diện URL gửi bởi khách hàng. Thiết lập kết nối được đạt được bằng cách sử dụng các yếu tố sau:
- URL Kết Nối URL kết nối chỉ định thông tin cần thiết cho việc kết nối đến một cơ sở dữ liệu cụ thể. Cú Pháp:
jdbc:<protocol>:<subprotocol>:<subname>
trong đó,
protocol
: Giao thức trong URL JDBC xác định tên giao thức để truy cập cơ sở dữ liệu.subprotocol
: Thành phần thứ haisubprotocol
nhận diện nguồn dữ liệu cơ sở dữ liệu cơ bản.subname
: Thành phần cuối cùngsubname
nhận diện tên cơ sở dữ liệu. Ví dụ URL kết nối:
jdbc:mysql://localhost:3306/test
Ở đây, kết nối đang được thực hiện với một máy chủ cơ sở dữ liệu MySQL có trên hệ thống cục bộ (truy cập qua localhost) qua cổng 3306 và tên cơ sở dữ liệu là test.
Ví dụ khác:
jdbc:sqlserver://127.0.0.1:1433
Ở đây, kết nối đang được thực hiện với máy chủ cơ sở dữ liệu SQL Server có trên hệ thống cục bộ (truy cập qua 127.0.0.1) qua cổng mặc định 1433. Tên cơ sở dữ liệu không được xác định ở đây, nên sẽ sử dụng cơ sở dữ liệu mặc định.
Những người phát triển cần tải và thêm các tệp JAR phù hợp từ trang web Oracle để mã xử lý cơ sở dữ liệu chạy đúng cách. Ví dụ, một ứng dụng sử dụng cơ sở dữ liệu MySQL có thể yêu cầu phải có tệp mysql-connector-java-8.0.20.jar
được đính kèm vào dự án.
Để thực hiện điều này, hãy truy cập link MySQL :: Download Connector/J, tải xuống và giải nén tệp zip. Sau đó, trong NetBeans, dưới dự án của bạn, chuột phải vào Libraries, chọn Add JAR/Folder, và sau đó, thêm tệp JAR đã giải nén.
Hình dưới mô tả bước này:
Nếu bạn tạo một dự án Java Maven trong Apache NetBeans, không có tùy chọn Thư viện hoặc Thêm JAR, và không cần phải tải bất kỳ tệp JAR nào. Thay vào đó, bạn phải thêm một phụ thuộc bằng cách sử dụng tệp pom.xml
trong dự án của bạn. Ví dụ, để kết nối đến cơ sở dữ liệu MySQL, phụ thuộc cần được thêm vào pom.xml
như sau:
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
Nếu bạn khởi tạo dự án bằng Maven từ NetBeans, quản lý các phụ thuộc thường được thực hiện thông qua tệp pom.xml
, và không cần phải thêm thủ công các tệp JAR vào thư viện như trong dự án NetBeans thông thường.
Ở đây, 8.0.21 là phiên bản của MySQL. Khi tệp pom.xml được cấu hình với phụ thuộc cơ sở dữ liệu phù hợp, Maven sẽ tìm kiếm các thư viện đó trong kho lưu trữ Maven trung tâm. Do đó, nhà phát triển không cần phải thêm thư viện một cách tường minh. Bước này chỉ áp dụng cho các dự án Maven.
DriverManager.getConnection()
Việc gọi phương thức getConnection()
liên quan đến một quá trình hai bước. Bước đầu tiên, so khớp URL và Trình điều khiển, được tiếp theo bởi việc kết nối đến cơ sở dữ liệu, đó là bước thứ hai.
Cú pháp:
Connection cn = DriverManager.getConnection(<connection_url>, <username>, <password>);
Phương thức getConnection()
thường chấp nhận hai đối số. Đối số đầu tiên là chuỗi URL kết nối của cơ sở dữ liệu và thứ hai là bộ thuộc tính đăng nhập như tên người dùng và mật khẩu.
Đoạn mã dưới mô tả cách sử dụng DriverManager.getConnection()
:
Connection cn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "");
Ví dụ:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcExample {
public static void main(String[] args) {
// Database URL
String url = "jdbc:mysql://127.0.0.1:3306/test";
// Database credentials
String username = "root";
String password = "";
try {
// Register JDBC driver
Class.forName("com.mysql.cj.jdbc.Driver");
// Open a connection
Connection connection = DriverManager.getConnection(url, username, password);
// Check if the connection is successful
if (connection != null) {
System.out.println("Connected to the database!");
// Perform database operations here
// Close the connection
connection.close();
System.out.println("Connection closed.");
} else {
System.out.println("Failed to connect to the database.");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
}
Tạo Các câu lệnh truy vấn
Khi một kết nối được thiết lập với cơ sở dữ liệu, một đối tượng Statement phải được tạo để thực hiện truy vấn. Đối tượng Statement là đối tượng được sử dụng phổ biến nhất để thực hiện các truy vấn SQL mà không yêu cầu truyền bất kỳ tham số nào.
Đối tượng Statement được tạo bằng cách sử dụng phương thức Connection.createStatement()
. Một đối tượng Statement có thể được phân loại thành ba loại dựa trên loại câu lệnh SQL được gửi đến cơ sở dữ liệu. Statement
và PreparedStatement
được kế thừa từ giao diện Statement
, CallableStatement
được kế thừa từ giao diện PreparedStatement
và thực thi một cuộc gọi đến thủ tục lưu trữ. Một đối tượng PreparedStatement
thực thi một câu lệnh SQL được biên dịch trước với hoặc không có tham số.
Cú pháp:
public Statement createStatement() throws SQLException
Ở đây, Statement
là đối tượng Statement (có thể hiểu như đối tượng câu lệnh) được trả về khi thực hiện phương thức createStatement()
.
Đoạn mã dưới thể hiện việc tạo một đối tượng Statement. Ở đây, cn
được giả định là một đối tượng Connection đã tồn tại. Mã được giả định được bao bọc trong một khối try-catch.
Ví dụ đoạn mã:
Statement st = cn.createStatement();
Ở đây, st
là đối tượng câu lệnh, được tạo và liên kết với một đối tượng kết nối duy nhất cn
.
Sử Dụng executeQuery() và Đối Tượng ResultSet
Khi đối tượng Statement
được tạo, nó có các phương thức để thực hiện các hoạt động cơ sở dữ liệu khác nhau.
Phương thức executeQuery()
là một trong những phương thức đó, nó lấy thông tin từ cơ sở dữ liệu. Nó chấp nhận một câu lệnh SQL SELECT đơn giản làm tham số và trả về các dòng cơ sở dữ liệu dưới dạng một đối tượng ResultSet
. Do đó, thực hiện truy vấn cơ sở dữ liệu dựa trên các bước sau:
executeQuery()
: Phương thức này được sử dụng để thực hiện bất kỳ câu lệnh SQL nào có một mệnh đề SELECT, trả kết quả của truy vấn dưới dạng mộtResultSet
. Nó nhận chuỗi truy vấn SQL làm tham số.- Đối tượng
ResultSet
: Đối tượngResultSet
được sử dụng để nhận và lưu trữ dữ liệu theo cùng định dạng như nó được trả về từ các truy vấn SQL. Đối tượngResultSet
thường được tạo bằng cách sử dụng phương thứcexecuteQuery()
.
Ví dụ:
Statement statement = cn.createStatement();
String sqlQuery = "SELECT * FROM your_table_name";
ResultSet resultSet = statement.executeQuery(sqlQuery);
// Now you can work with the ResultSet to retrieve and process data
while (resultSet.next()) {
// Process each row of data
String columnName = resultSet.getString("column_name");
// Perform actions with the retrieved data
}
// Don't forget to close the ResultSet when done
resultSet.close();
Ở đây, your_table_name
là tên bảng của bạn và column_name
là tên cột mà bạn muốn truy xuất từ ResultSet
.
Cú Pháp:
public ResultSet executeUpdate(String sql) throws SQLException
Trong đó:
sql
là một đối tượng String chứa câu lệnh SQL sẽ được gửi đến cơ sở dữ liệu.ResultSet
là một đối tượng được tạo để lưu trữ kết quả của câu lệnh SQL.
Đoạn Mã dưới thể hiện việc sử dụng phương thức executeUpdate()
để chọn một số bản ghi từ cơ sở dữ liệu.
ResultSet rs = statement.executeQuery("SELECT * FROM Employees");
Ở đây, rs
là đối tượng ResultSet
được tạo để lưu trữ kết quả của câu lệnh SELECT.
Ví dụ:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class ExecuteQueryExample {
public static void main(String[] args) {
// JDBC connection parameters
String jdbcUrl = "jdbc:mysql://localhost:3306/your_database";
String username = "your_username";
String password = "your_password";
// SQL query to be executed
String sqlQuery = "SELECT * FROM your_table";
// Establishing a JDBC connection
try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) {
// Creating a statement
try (Statement statement = connection.createStatement()) {
// Executing the query
ResultSet resultSet = statement.executeQuery(sqlQuery);
// Processing the result set
while (resultSet.next()) {
// Accessing columns by name or index
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
// Process the retrieved data as needed
System.out.println("ID: " + id + ", Name: " + name);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Sử Dụng Các Phương Thức executeUpdate() và execute()
Các phương thức khác của giao diện Statement
như sau:
executeUpdate()
: Phương thức này được sử dụng để thực hiện các câu lệnh INSERT, DELETE, UPDATE và các câu lệnh Ngôn ngữ Định nghĩa Dữ liệu SQL (DDL) khác như CREATE TABLE, DROP TABLE, v.v. Phương thức trả về một giá trị nguyên chỉ số hàng được tác động. Cú Pháppublic int executeUpdate(String sql) throws SQLException
Trong đó:sql
là một đối tượng String được tạo để lưu trữ kết quả của câu lệnh SQL.int
là một giá trị nguyên lưu trữ số hàng bị tác động.
execute()
: Phương thức này được sử dụng để thực hiện các câu lệnh SQL trả về nhiều hơn một bộ kết quả. Phương thức trả về true nếu một đối tượngResultSet
được tạo ra bởi các câu lệnh SQL. Cú Pháppublic boolean execute(String sql) throws SQLException
Trong đó:sql
là một đối tượng String được tạo để lưu trữ kết quả của câu lệnh SQL.
2 Đoạn Mã dưới thể hiện cách sử dụng các phương thức executeUpdate()
và execute()
.
Đoạn mã 1:
int rowCount = statement.executeUpdate("DELETE FROM Employees WHERE Salary < 50000");
System.out.println("Number of rows deleted: " + rowCount);
Ở đây, executeUpdate()
được sử dụng để thực hiện câu lệnh DELETE và trả về số hàng đã bị xóa.
Đoạn mã 2:
boolean hasResultSet = statement.execute("SELECT * FROM Employees");
if (hasResultSet) {
ResultSet resultSet = statement.getResultSet();
// Process the result set
} else {
System.out.println("No result set generated.");
}
Ở đây, execute()
được sử dụng để thực hiện câu lệnh SELECT và kiểm tra xem một đối tượng ResultSet
có được tạo ra hay không.
Ví dụ:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class ExecuteExample {
public static void main(String[] args) {
// JDBC connection parameters
String jdbcUrl = "jdbc:mysql://localhost:3306/your_database";
String username = "your_username";
String password = "your_password";
// SQL queries
String selectQuery = "SELECT * FROM your_table";
String updateQuery = "UPDATE your_table SET column1 = 'new_value' WHERE column2 = 'some_condition'";
// Establishing a JDBC connection
try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) {
// Creating a statement
try (Statement statement = connection.createStatement()) {
// Executing a SELECT query using execute()
boolean isResultSet = statement.execute(selectQuery);
if (isResultSet) {
// If the result is a ResultSet (SELECT query)
// Process the result set as needed
} else {
// If the result is an update count or there is no result (UPDATE, INSERT, DELETE)
int updateCount = statement.getUpdateCount();
System.out.println("Rows affected: " + updateCount);
}
// Executing an UPDATE query using executeUpdate()
int rowsAffected = statement.executeUpdate(updateQuery);
System.out.println("Rows affected by UPDATE: " + rowsAffected);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Tạo Truy Vấn Tham Số
PreparedStatement
là đối tượng thực hiện việc thực thi các câu lệnh SQL động với tham số. Do đó, để sử dụng một truy vấn có tham số, bước đầu tiên là tạo đối tượng PreparedStatement
. Như trong trường hợp của đối tượng Statement
, đối tượng PreparedStatement
cũng cần được tạo bởi một đối tượng Connection
.
Tạo Truy Vấn Có Tham Số
Đối tượng PreparedStatement
được tạo bằng cách sử dụng phương thức prepareStatement()
của lớp Connection
. Phương thức này chấp nhận một câu lệnh SQL làm đối số, khác với đối tượng Statement
. Vì đây được coi là một câu lệnh được biên soạn trước, cơ sở dữ liệu phải biết câu lệnh SQL.
Đối với các tham số chạy vào một câu lệnh SQL động, một ký tự đại diện “?” được sử dụng để chỉ định rằng một biến được mong đợi ở đó.
Ví dụ Sử Dụng:
String sqlQuery = "INSERT INTO Employees (Name, Age, Salary) VALUES (?, ?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);
Ở đây, sqlQuery
là câu lệnh SQL có tham số, và ?
là các vị trí của tham số.
Để gán giá trị cho các tham số, chúng ta có thể sử dụng các phương thức set
của PreparedStatement
, ví dụ:
preparedStatement.setString(1, "John Doe");
preparedStatement.setInt(2, 30);
preparedStatement.setDouble(3, 50000.0);
Như vậy, câu lệnh SQL cuối cùng sẽ có giá trị như sau:
INSERT INTO Employees (Name, Age, Salary) VALUES ('John Doe', 30, 50000.0);
Tùy thuộc vào loại dữ liệu và vị trí của tham số, bạn có thể sử dụng các phương thức set
khác nhau của PreparedStatement
.
Ví dụ:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PreparedStatementExample {
public static void main(String[] args) {
// JDBC connection parameters
String jdbcUrl = "jdbc:mysql://localhost:3306/your_database";
String username = "your_username";
String password = "your_password";
// SQL query with parameters
String selectQuery = "SELECT * FROM your_table WHERE column1 = ?";
String updateQuery = "UPDATE your_table SET column2 = ? WHERE column1 = ?";
// Parameter values
String parameterValue = "some_value";
String updateColumnValue = "new_value";
// Establishing a JDBC connection
try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) {
// Example of executing a SELECT query with PreparedStatement
try (PreparedStatement selectStatement = connection.prepareStatement(selectQuery)) {
// Setting parameter values
selectStatement.setString(1, parameterValue);
// Executing the query
ResultSet resultSet = selectStatement.executeQuery();
// Processing the result set
while (resultSet.next()) {
// Accessing columns by name or index
int id = resultSet.getInt("id");
String column1Value = resultSet.getString("column1");
// Process the retrieved data as needed
System.out.println("ID: " + id + ", column1: " + column1Value);
}
}
// Example of executing an UPDATE query with PreparedStatement
try (PreparedStatement updateStatement = connection.prepareStatement(updateQuery)) {
// Setting parameter values
updateStatement.setString(1, updateColumnValue);
updateStatement.setString(2, parameterValue);
// Executing the update
int rowsAffected = updateStatement.executeUpdate();
System.out.println("Rows affected by UPDATE: " + rowsAffected);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Tạo Các Truy Vấn Tham Số
PreparedStatement
thực hiện việc thực thi các câu lệnh SQL động với tham số. Do đó, để sử dụng một truy vấn có tham số, bước đầu tiên là tạo đối tượng PreparedStatement
. Giống như đối tượng Statement
, đối tượng PreparedStatement
cũng cần được tạo bởi một đối tượng Connection
.
Tạo Truy Vấn Có Tham Số
PreparedStatement
được tạo bằng cách sử dụng phương thức prepareStatement()
của lớp Connection
. Phương thức này chấp nhận một câu lệnh SQL làm đối số, khác với đối tượng Statement
. Vì đây được coi là một câu lệnh được biên soạn trước, cơ sở dữ liệu phải biết câu lệnh SQL.
Đối với tham số chạy vào một câu lệnh SQL động, một ký tự đại diện “?” được sử dụng để chỉ định rằng một biến được mong đợi ở đó.
Đoạn mã dưới mô tả cách tạo truy vấn có tham số:
String sqlStmt = "UPDATE Department SET Dept_ID=? WHERE Dept_Name LIKE ?";
PreparedStatement pstmt = connection.prepareStatement(sqlStmt);
Ở đây, sqlStmt
là câu lệnh SQL có tham số, và ?
là các vị trí của tham số.
Để gán giá trị cho các tham số, chúng ta có thể sử dụng các phương thức set
của PreparedStatement
. Ví dụ:
pstmt.setInt(1, 25);
pstmt.setString(2, "Production");
Như vậy, 1
và 2
đại diện cho vị trí của tham số trong câu lệnh SQL, và chúng ta gán giá trị cho chúng. Sau đó, để thực thi truy vấn, chúng ta sử dụng phương thức executeUpdate()
.
pstmt.executeUpdate();
Phương thức này trả về số lượng hàng bị ảnh hưởng bởi thao tác cập nhật, và thường được sử dụng cho các truy vấn UPDATE, INSERT và DELETE.
Ví dụ:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ParameterizedQueryExample {
public static void main(String[] args) {
// JDBC connection parameters
String jdbcUrl = "jdbc:mysql://localhost:3306/your_database";
String username = "your_username";
String password = "your_password";
// SQL query with a parameter
String sqlQuery = "SELECT * FROM your_table WHERE age > ?";
// Example parameter value
int minAge = 25;
// Establishing a JDBC connection
try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) {
// Creating a PreparedStatement
try (PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery)) {
// Setting the parameter value
preparedStatement.setInt(1, minAge);
// Executing the query
ResultSet resultSet = preparedStatement.executeQuery();
// Processing the result set
while (resultSet.next()) {
// Accessing columns by name or index
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
// Process the retrieved data as needed
System.out.println("ID: " + id + ", Name: " + name);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Xử Lý Ngoại Lệ trong Ứng Dụng JDBC
Trong quá trình làm việc với ứng dụng cơ sở dữ liệu và JDBC API, đôi khi có những tình huống có thể gây ra ngoại lệ. Các ngoại lệ phổ biến xảy ra trong quá trình xử lý cơ sở dữ liệu với JDBC như sau:
ClassNotFoundException
Khi tải một trình điều khiển bằng Class.forName()
, nếu lớp cho trình điều khiển cụ thể không có trong gói, phương thức sẽ ném một ClassNotFoundException
.
Do đó, phương thức nên được đặt trong một khối try
, tiếp theo là một khối catch
để xử lý ngoại lệ nếu có (nếu có).
Mã Mẫu:
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace(); // or handle the exception in an appropriate way
}
Trong trường hợp ngoại lệ, chúng ta có thể in thông điệp ngoại lệ hoặc xử lý nó một cách thích hợp theo yêu cầu của ứng dụng.
SQLException
Mọi phương thức được định nghĩa bởi các đối tượng JDBC như Connection, Statement và ResultSet đều có thể ném ra java.sql.SQLException
. Do đó, mỗi khi sử dụng các phương thức này, chúng nên được bao bọc bên trong một khối try...catch
để xử lý các ngoại lệ. Mã lỗi cụ thể của nhà cung cấp được chèn vào đối tượng SQLException
, và nó có thể được truy xuất bằng cách sử dụng phương thức getErrorCode()
.
Mã Mẫu:
try {
// JDBC operations that may throw SQLException
} catch (SQLException e) {
int errorCode = e.getErrorCode();
e.printStackTrace(); // or handle the exception in an appropriate way
}
Trong trường hợp ngoại lệ, chúng ta có thể truy xuất mã lỗi cụ thể hoặc xử lý nó một cách thích hợp tùy thuộc vào yêu cầu của ứng dụng.
Xử lý truy vấn
Sau khi truy vấn cơ sở dữ liệu được thực hiện và đối tượng ResultSet được tạo, bước tiếp theo là xử lý và
truy xuất kết quả từ ResultSet. Do dữ liệu trong ResultSet được trả về dưới dạng bảng và con trỏ được đặt trước dòng đầu tiên, nó phải duyệt qua các dòng sử dụng phương thức next(). Phương thức next() cho phép di chuyển tiến bằng cách di chuyển con trỏ một dòng về phía trước.
Nó trả về giá trị boolean true nếu vị trí con trỏ hiện tại đang ở trên một dòng hợp lệ và trả về false khi con trỏ được đặt ở vị trí sau dòng cuối cùng.
Mã Mẫu:
ResultSet rs = stmt.executeQuery("SELECT EmployeeName FROM Employees");
while (rs.next()) {
String name = rs.getString("EmployeeName");
System.out.println(name);
}
Ở đây, mã lấy tên nhân viên từ bảng Employees và hiển thị chúng dưới dạng chuỗi sử dụng phương thức next().
Phương Thức để Xử Lý Các Truy Vấn
Các phương thức getter được sử dụng để trích xuất dữ liệu từ dòng hiện tại của đối tượng Result Set và lưu trữ nó vào một biến Java tương ứng với kiểu dữ liệu. Các phương thức này được khai báo bởi giao diện ResultSet để truy xuất giá trị cột bằng cách sử dụng số chỉ mục hoặc tên của cột. Trong trường hợp có nhiều hơn một cột có cùng tên, giá trị của cột khớp đầu tiên sẽ được trả về. Dưới đây là một số phương thức getter để lấy giá trị của các kiểu dữ liệu Java khác nhau:
getString()
Phương thức getString()
được sử dụng để lấy giá trị chuỗi (kiểu SQL VARCHAR) từ dòng hiện tại và gán vào đối tượng chuỗi Java.
getInt()
Phương thức getInt()
được sử dụng để lấy giá trị số nguyên từ dòng hiện tại và gán vào một biến số nguyên Java.
getFloat()
Phương thức getFloat()
được sử dụng để lấy giá trị số thực từ dòng hiện tại và gán vào một biến số thực Java.
getObject()
Phương thức getObject()
được sử dụng để lấy giá trị từ dòng hiện tại dưới dạng một đối tượng và gán cho đối tượng trong ngôn ngữ lập trình Java.
Mã Mẫu:
while (rs.next()) {
String name = rs.getString("EmployeeName");
int deptId = rs.getInt("Department_Id");
float rating = rs.getFloat("Rating");
System.out.println(name + " " + deptId + " " + rating);
}
Ở đây, giá trị tên, phòng ban và điểm được trích xuất từ các cột tương ứng và lưu trữ trong các biến thuộc các kiểu dữ liệu tương ứng của ngôn ngữ lập trình Java. Các giá trị trong các biến cuối cùng được hiển thị.
Đóng Kết Nối Cơ Sở Dữ Liệu
Bước cuối cùng nhưng quan trọng trong một ứng dụng cơ sở dữ liệu là đóng cả kết nối và bất kỳ câu lệnh nào đang mở, sau khi quá trình xử lý hoàn tất. Kết nối mở có thể gây ra vấn đề bảo mật. Một phương thức đơn giản close()
được cung cấp bởi các đối tượng Connection, Statement và ResultSet để đạt được mục đích này. Để giữ cho các phương thức giải phóng cơ sở dữ liệu gọn gàng và luôn giải phóng kết nối (ngay cả khi có một ngoại lệ có thể được ném), kết nối cơ sở dữ liệu nên được đóng trong một khối finally
.
Cú Pháp:
public void close()
Phương thức này giải phóng tài nguyên JDBC và kết nối cơ sở dữ liệu ngay lập tức. Đoạn mã Snippet 13 dưới đây thể hiện cách sử dụng phương thức close()
:
Mã Mẫu:
stmt.close();
conn.close();
Ở đây, đối tượng Statement và Connection đã được đóng bằng cách sử dụng phương thức close()
.
8.6 Thông Tin Metadata Cơ Sở Dữ Liệu
Metadata trong ngữ cảnh cơ sở dữ liệu có nghĩa là dữ liệu về dữ liệu. Trong ngữ cảnh của cơ sở dữ liệu, metadata còn được định nghĩa là thông tin mô tả cấu trúc và thuộc tính của dữ liệu được lưu trữ trong cơ sở dữ liệu. JDBC hỗ trợ truy cập metadata bằng cách cung cấp một số phương thức. Ví dụ, một bảng trong cơ sở dữ liệu có tên, các tên cột, kiểu dữ liệu cho các cột và chủ sở hữu của bảng đó, mô tả này được gọi là metadata.
Giao Diện DatabaseMetaData
Thông tin mô tả về cơ sở dữ liệu chính là metadata của cơ sở dữ liệu. Thông tin metadata này được lưu trữ bởi các đối tượng của giao diện DatabaseMetaData trong gói java.sql.
Để tạo một đối tượng DatabaseMetaData, một trường hợp mới của giao diện DatabaseMetaData được tạo. Đối tượng mới tạo này được gán với các kết quả được lấy bằng cách gọi phương thức getMetaData()
trên đối tượng Connection.
Mã Mẫu:
DatabaseMetaData metaData = connection.getMetaData();
Ví dụ:
DatabaseMetaData metaData = connection.getMetaData();
Ở đây, connection
là một đối tượng của lớp Connection.
Các Phương Thức của DatabaseMetaData
Giao diện DatabaseMetaData cũng tiết lộ một thư viện các phương thức để hiển thị thông tin liên quan đến cơ sở dữ liệu. Dựa trên loại thông tin có thể được lấy bằng các phương thức, dưới đây là một số phương thức được liệt kê trong Bảng dưới.
Loại | Tên Phương Thức | Mô Tả |
Escape Characters | getSearchStringEscape() | Lấy và trả về chuỗi để tránh ký tự đại diện cho ký tự thoát. |
Thông Tin Cơ Sở Dữ Liệu | getDatabaseProductName() | Lấy tên của sản phẩm cơ sở dữ liệu đã kết nối và trả về dưới dạng chuỗi. |
Thông Tin Cơ Sở Dữ Liệu | getDatabaseProductVersion() | Lấy số phiên bản của sản phẩm cơ sở dữ liệu đã kết nối và trả về dưới dạng chuỗi. |
Thông Tin Cơ Sở Dữ Liệu | isReadOnly() | Trả về giá trị boolean là true nếu cơ sở dữ liệu ở dạng chỉ đọc, ngược lại trả về giá trị false. |
Thông Tin Driver | getDriverName() | Lấy tên của driver JDBC đang sử dụng và trả về dưới dạng chuỗi. |
Thông Tin Driver | getDriverVersion() | Lấy số phiên bản của driver JDBC đang sử dụng và trả về dưới dạng chuỗi. |
Thông Tin Driver | getDriverMajorVersion() | Lấy số phiên bản chính của driver JDBC đang sử dụng và trả về dưới dạng số nguyên. |
Một số phương thức khác:
Phương thức | Mô tả Phương thức |
getURL() | Phương thức này trả về URL cho hệ quản trị cơ sở dữ liệu này dưới dạng một chuỗi |
getUserName() | Phương thức này trả về tên người dùng như được biết đến trong cơ sở dữ liệu dưới dạng một đối tượng String. |
getConnection() | Phương thức này trả về đối tượng kết nối mà đã tạo ra đối tượng siêu dữ liệu này. |
supportsPositionedDelete() | Phương thức này trả về một giá trị boolean là true hoặc false tùy thuộc vào việc cơ sở dữ liệu có hỗ trợ câu lệnh DELETE có vị trí hay không. |
supportsPositionedUpdate() | Phương thức này trả về một giá trị boolean là true hoặc false tùy thuộc vào việc cơ sở dữ liệu có hỗ trợ câu lệnh UPDATE có vị trí hay không. |
supportsTransactions() | Phương thức này trả về liệu cơ sở dữ liệu có hỗ trợ giao dịch và trả về một giá trị boolean là true nếu giao dịch được hỗ trợ, ngược lại trả về false. |
Giao diện ResultSetMetaData
Mô tả: Thông tin mô tả về dữ liệu chứa trong một ResultSet được biết đến là Resultset metadata. Thông tin metadata này được lưu trữ bởi các đối tượng của giao diện ResultSetMetaData trong gói java.sql. Đối tượng này có thể cung cấp thông tin về các thuộc tính như tên cột, số lượng cột và kiểu dữ liệu cho các cột trong kết quả.
Để lấy tất cả thông tin này: Một đối tượng ResultSetMetaData được tạo ra và được gán với các kết quả được lấy bằng phương thức getMetaData(), được gọi bởi đối tượng ResultSet.
Đoạn mã dưới mô tả quá trình tạo ra một đối tượng ResultSetMetabata.
ResultSetMetaData md = re.getMetaData();
Khi một ứng dụng Java nhận được một kết nối hợp lệ và thành công lấy dữ liệu từ cơ sở dữ liệu vào một tập kết quả, đoạn mã này tạo ra một đối tượng ResultSetMetaData.
Phương thức ResultSetMetaData
Giao diện ResultSetMetaData cung cấp một số phương thức để lấy thông tin về các dòng và cột trong ResultSet. Những phương thức này chỉ có thể được gọi bằng cách sử dụng đối tượng Resultset thay vì sử dụng đối tượng Connection. Dưới đây là một số phương thức được sử dụng rộng rãi được cung cấp bởi giao diện ResultSetMetaData:
getColumnName()
Phương thức này trả về tên của cột cụ thể dưới dạng một chuỗi.
Cú pháp:
public String getColumnName(int column) throws SQLException
Trong đó:
– `String` là kiểu trả về của phương thức chứa tên cột.
– `column` là số cột trong định dạng số nguyên,
Đoạn mã dưới cho thấy cách sử dụng phương thức `getColumnName()`.
String colName = resultSet.getColumnName(2);
Ở đây, phương thức sẽ lấy tên của cột thứ hai từ ResultSet và lưu giá trị tên cột vào biến `colName`.
getColumnCount()
Phương thức này trả về số cột trong ResultSet hiện tại dưới dạng số nguyên.
Cú pháp:
public int getColumnCount() throws SQLException
Trong đó:
– `int` là kiểu trả về của phương thức trả về số cột.
Phương thức này cũng ném một SQLException trong trường hợp có lỗi truy cập cơ sở dữ liệu.
Đoạn mã dưới cho thấy cách sử dụng phương thức `getColumnCount()`:
int totalCols = resultSet.getColumnCount();
Ở đây, phương thức sẽ lấy số cột trong ResultSet và lưu giá trị số nguyên vào biến `totalCols`.
getColumnType()
Phương thức này trả về loại SQL của cột cụ thể dưới dạng chuỗi. Cú pháp:
public int getColumnType(int column) throws SQLException
Trong đó:
– `int` là kiểu trả về của phương thức trả về loại SQL của các cột được chỉ định.
– `column` là số cột trong định dạng số nguyên,
Đoạn mã dưới cho thấy cách sử dụng phương thức `getColumnType()`:
int colType = resultSet.getColumnType(1);
Ở đây, phương thức sẽ lấy loại SQL của cột đầu tiên từ ResultSet và lưu giá trị chuỗi vào biến `colType`.
Here is the corrected and translated text:
8.6.5 Kết nối đến Cơ sở dữ liệu SQL Server bằng Type 4
Driver Microsoft SQL Server là một cơ sở dữ liệu rộng rãi được sử dụng từ Microsoft. Nó cho phép người dùng thao tác dữ liệu với một số lượng lớn các loại dữ liệu, thủ tục lưu trữ và cung cấp một nền tảng an toàn để phát triển ứng dụng cơ sở dữ liệu doanh nghiệp. Ứng dụng Java có thể kết nối với SQL Server thông qua Type 4 JDBC Driver.
Nhà phát triển có thể tải nó từ liên kết sau: https://docs.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server?view=sql-server-ver15
Sau đó,có thể thêm nó như một tệp JAR vào ứng dụng. Cú pháp để thiết lập kết nối đến cơ sở dữ liệu SQL Server như sau: Cú pháp
jdbc:sqlserver://serverName;instanceName=value;portNumber=value;property=value
Trong đó,
– `jdbc:sqlserver://` là một chuỗi bắt buộc đại diện cho giao thức con và là hằng số.
– `serverName` và `instanceName` là tùy chọn và xác định địa chỉ của máy chủ và phiên bản trên máy chủ để kết nối. `serverName` có thể là localhost hoặc địa chỉ IP của máy tính cục bộ.
– `portNumber` chỉ định cổng để kết nối đến `serverName`. Nếu không chỉ định, mặc định là 1433.
– `property` xác định thông tin đăng nhập như tên người dùng và mật khẩu.
Đoạn mã dưới mô tả một ví dụ về chuỗi kết nối có thể được sử dụng để kết nối đến cơ sở dữ liệu SQL:
jdbc:sqlserver://localhost;user=sa;password=hello;
Dòng mã này kết nối đến cơ sở dữ liệu mặc định trên máy tính cục bộ bằng cách chỉ định tên người dùng và mật khẩu. Đoạn mã dưới thể hiện một ví dụ khác về cách kết nối đến cơ sở dữ liệu SQL Server:
String url = "jdbc:sqlserver://127.0.0.1:1433;instanceName=ABC\SQLEXPRESS;databaseName=mydb";
Connection cn = DriverManager.getConnection(url, "sa", "123456");
try {
// Các thao tác trên cơ sở dữ liệu ở đây
} catch (SQLException ce) {
System.out.println("Lỗi: " + ce.getMessage());
}
Ở đây, mã kết nối đến cơ sở dữ liệu mydb tại phiên bản ABC\SQLEXPRESS, trên máy tính cục bộ, có tên người dùng là sa và mật khẩu là 123456. Các mã này và bất kỳ mã nào liên quan đến các thao tác cơ sở dữ liệu có thể gây ra ngoại lệ nên được đặt trong các khối try-catch thích hợp. Trong trường hợp này, có thể có một SQLException được ném, do đó, mã có một khối catch cho ngoại lệ này. Lưu ý rằng cần thêm các lệnh import cần thiết để biên dịch mã thành công.
Bài tập
Bài 1
Câu 1:
- Tạo một lớp Java có tên
Employee
để lưu thông tin về nhân viên với các thuộc tính sau:private String employeeID
private String fullName
private String address
private int age
Employee
:- Tạo hai constructor:
- Một constructor mặc định.
- Một constructor với các tham số để gán giá trị cho các thuộc tính.
- Cung cấp phương thức
getter
vàsetter
cho các thuộc tính trên. - Ghi đè phương thức
toString()
để trả về thông tin đầy đủ của nhân viên.
- Tạo lớp
EmployeeTest
để kiểm tra chức năng của lớpEmployee
. Lớp này yêu cầu:- (1) Nhập vào thông tin của 5 nhân viên từ bàn phím và thêm chúng vào một danh sách (
List<Employee>
). Sử dụng góijava.io
để nhập dữ liệu từ bàn phím (không dùngScanner
). Sử dụng generic để lưu danh sách nhân viên. - (2) Kiểm tra
employeeID
hợp lệ bằng biểu thức chính quy (regular expression
). Định dạngemployeeID
phải như sau: 2 ký tự chữ cái, tiếp theo là 4 chữ số và kết thúc bằng 1 hoặc 2 ký tự chữ cái. Ví dụ, các giá trị hợp lệ làAB1234C
,XY5678D
,ZZ0000EF
, và các giá trị không hợp lệ làA1234
,X12345G
,XY123H1
. - (3) Ghi danh sách nhân viên vào một tệp có tên
employee.dat
. - (4) Đọc tệp
employee.dat
để lấy danh sách nhân viên và hiển thị ra màn hình console. - (5) Từ danh sách nhân viên đọc được, hiển thị tất cả nhân viên có tuổi lớn hơn 25.
- (1) Nhập vào thông tin của 5 nhân viên từ bàn phím và thêm chúng vào một danh sách (
Câu 2:
- Tạo một lớp có tên
WordContainer
để lưu trữ một mảng chuỗiString[] words = {"Sai Gon", "Da Nang", "Hue"}
. - Tạo một lớp có tên
UppercaseThread.java
để lấy từng chuỗi từ mảng trongWordContainer
, chuyển đổi chuỗi thành chữ in hoa và truyền chuỗi đã chuyển đổi này đếnDisplayThread
để hiển thị. - Tạo một lớp có tên
DisplayThread.java
để hiển thị chuỗi đã chuyển đổi in hoa từ lớpUppercaseThread
. Ví dụ, khiUppercaseThread
gửi chuỗi"Sai Gon"
thìDisplayThread
sẽ hiển thị"SAI GON"
. - Tạo một lớp có tên
ThreadTest
để kiểm tra hai lớp trên.
Phần 2 - HttpClient
Bài tập 1: Gửi yêu cầu GET đơn giản
- Mô tả:
- Sử dụng
HttpClient
(Java 11) gửi yêu cầu GET đến một endpoint công khai, ví dụ:https://api.github.com/
. - Lấy và in ra status code, header và body của phản hồi.
- Sử dụng
- Yêu cầu:
- Khởi tạo
HttpClient
vớiHttpClient.newHttpClient()
. - Tạo
HttpRequest
vớiHttpRequest.newBuilder()
và URL tương ứng. - Thực hiện
client.send()
hoặcclient.sendAsync()
để nhậnHttpResponse
. - In ra mã phản hồi (
response.statusCode()
), headers (response.headers()
) và nội dung (response.body()
).
- Khởi tạo
Bài tập 2: Gửi yêu cầu GET với query parameters
-
Mô tả:
- Gửi yêu cầu GET đến một public API có tham số query, ví dụ:
https://api.agify.io?name=michael
(API này đoán tuổi dựa trên tên). - Trích xuất dữ liệu từ phản hồi (dạng JSON) và in ra tên, tuổi dự đoán.
- Gửi yêu cầu GET đến một public API có tham số query, ví dụ:
-
Yêu cầu:
- Sử dụng
HttpRequest
để gửi GET request với query parameters. - Dùng
ObjectMapper
(từ Jackson) hoặc thư viện tương tự để parse JSON. - In ra thông tin như: Name:
michael
, Age:xx
.
- Sử dụng
Bài tập 3: Gửi yêu cầu POST với JSON payload
-
Mô tả:
- Tạo một request POST gửi đến một mock server (ví dụ:
https://httpbin.org/post
) với nội dung JSON đơn giản (ví dụ:{"username":"john","password":"1234"}
). - Parse phản hồi từ server và in ra nội dung server trả về.
- Tạo một request POST gửi đến một mock server (ví dụ:
-
Yêu cầu:
- Tạo
HttpRequest
dạng POST, set headerContent-Type: application/json
. - Body là chuỗi JSON.
- Gửi request, nhận phản hồi, parse phản hồi JSON và in ra.
- Tạo
Bài tập 4: Gửi yêu cầu PUT và DELETE
-
Mô tả:
- Giả sử bạn có một REST API giả lập trên
https://jsonplaceholder.typicode.com/posts
.- Gửi PUT request đến
https://jsonplaceholder.typicode.com/posts/1
để cập nhật một post giả (ví dụ title, body). - Gửi DELETE request đến
https://jsonplaceholder.typicode.com/posts/1
để xóa post.
- Gửi PUT request đến
- Kiểm tra status code của từng phản hồi.
- Giả sử bạn có một REST API giả lập trên
-
Yêu cầu:
- Sử dụng PUT request với JSON payload mới.
- Kiểm tra mã phản hồi (200, 204, v.v).
- Gửi DELETE request và kiểm tra mã phản hồi.
Bài tập 5: Xử lý lỗi và ngoại lệ
-
Mô tả:
- Gửi GET request đến một URL không tồn tại hoặc gây ra lỗi (ví dụ:
https://api.github.com/thispagedoesnotexist
). - Bắt và in ra lỗi 404 từ phản hồi.
- Mô phỏng một kết nối timeout, handle ngoại lệ
HttpTimeoutException
.
- Gửi GET request đến một URL không tồn tại hoặc gây ra lỗi (ví dụ:
-
Yêu cầu:
- Cấu hình
HttpRequest
vớitimeout()
. - Thử gửi request đến URL không hợp lệ để thấy cách handle status code 4xx, 5xx.
- Bắt các ngoại lệ và in ra thông báo lỗi thích hợp.
- Cấu hình