Truy cập CSDL
CSDL cần phải cho phép được truy nhập từ xa , cho phép nhiều NSD đồng thời. NSD cần có database client . database client giao tiếp với ...
CSDL cần phải cho phép được truy nhập từ xa ,
cho phép nhiều NSD đồng thời.
NSD cần có database client. database client giao tiếp với database server để phục vụ NSD.
ODBC và JDBC Drivers
Database clients sử dụng database drivers để gửi câu lệng SQL đến database servers và nhận kết quả trả lời .
Các ứng dụng Java và applet sử dụng JDBC drivers để giao tiếp với database servers.
Microsoft's ODBC
Nhiều database servers sử dụng các giao thức chuyên biệt của nhà sản xuất = một ngôn ngữ mới, riêng.
Microsoft : thiết lập một chuẩn chung để giao tiếp databases,
Open Database Connectivity (ODBC).
Trước khi có ODBC : database clients là phụ thuộc server.
ODBC drivers trừu tượng hoá các giao thức chuyên biệt của nhiều nhà sản xuất, cung cấp các API chung nhất cho database clients.
Xây dựng database clients sử dụng ODBC API, chương trình của bạn sẽ truy nhập được nhiều database servers.
Tại sao cần JDBC.
JDBC drivers không giao tiếp trực tiếp với nhiều sản phẩm CSDL như ODBC drivers.
Các JDBC drivers đầu tiên là JDBC-ODBC bridge driver do JavaSoft và Intersolv phát triển.
JDBC là giải pháp tốt hơn cho các ứng dụng Java và applets:
- ODBC là API viết bằng C, Nếu viết lại ODBC bằng Java sẽ cần thay đổi đáng kể các ODBC API.
- ODBC drivers phải được cài đặt trên máy khách.
Giải pháp gọi là thuần Java (pure Java) cần cho phép JDBC tự động tải xuống và cài đặt cùng với applet. Điều này làm cho NSD applet thuận lợi hợn.
JDBC-ODBC bridge driver chỉ là quá độ, không phải là một giải pháp đẹp.
Các kiểu JDBC driver.
JavaSoft đã phân loại JDBC drivers thành 4 kiểu driver :
- JDBC-ODBC bridge + ODBC driver
Sử dụng ODBC driver của Microsoft để giao tiếp với server CSDL.
Phải được cài đặt trước trên máy khách trước khi sử dụng.
- Native-API partly Java driver
Đây là các drivers mà nói với servers CSDL bằng các giao thức native của servers CSDL. Ví dụ Oracle driver sẽ nói bằng SQLNet, còn DB2 driver sẽ dùng giao thức CSDL của IBM .
Phải cài đặt trước trên máy khách.
- JDBC-Net pure Java driver.
Drivers thuần Java, sử dụng giao thức mạng chuẩn ví dụ HTTP để nói với database access server.
database access server thông dịch giao thức mạng thành giao thức của nhà sản xuất CSDL.
- Native-protocol pure Java driver
Driver thuần Java, sử dụng giao thức của nhà sản xuất CSDL được thiết kế để giao tác với nó.
Drivers thuần Java : kiểu 3, 4
Hỗ trợ zero installation đối với applets.
Driver kiểu 4 giao tiếp với server CSDL sử dụng giao thức riêng của nhà sản xuất.
Drives kiểu 3 sử dụng database access server, truyên thông với database access server bằng một giao thức mạng chuẩn.
Một ví dụ về kiẻu 3 là IDS JDBC driver
Tìm hiểu Driver
Để sử dụng JDBC, cần có database server và database driver.
Ví dụ Microsoft Access - phổ biến.
JDBC cung cấp truy nhập CSDL độc lập với server, dùng server nào là không quan trọng
Driver CSDL là cầu nối JDBC và CSDL.
JDBC đi kèm với JDBC-ODBC bridge.
Cầu nối này cho phép truy nhập CSDL thông qua Open Database Connectivity API của Microsoft.
Lớp DriverManager
java.sql
Lớp DriverManager : để quản trị các JDBC drivers được cài đặt trong hệ thống của bạn. Bằng cách thiết lập trực tiếp hoặc nạp dùng phương thức forName(). (Chương trình DriverApp dưới đây minh hoạ cách thức nạp JDBC driver dùng forName()).
DriverManager có Hai phương thức quan trọng nhất :
getDrivers() và getConnection()
GetDrivers() liệt kê mọi JDBC drivers được cài đặt trong hệ thống.
getConnection() sẽ thiết lập một kết nối tới CSDL. 3 dạng:
getCon nection(String url )
getConnection(String url ,String userID ,String password )
getConnection(String url ,Properties arguments )
Quy định về cách viết URL để thiết lập kết nối đến CSDL là khác nhau tuỳ theo JDBC drivers
Nói chung có dạng sau:
jdbc:subprotocol:subname
Ví dụ, JDBC-ODBC bridge
jdbc:odbc:subname
IDS JDBC driver dùng giao thức dạng
jdbc:ids:subname.
Subname của một giao thức CSDL chỉ ra CSDL và các tham số khác.
Ví dụ, URL để thiết lập kết nối đến CSDL của Microsoft Access có tên là DataSetName tại máy chủ cx122974-a.cv1.sdca.home.com tại cổng 80, có dạng sau :
jdbc:ids://cx122974-a.cv1.sdca.home.com:80/ conn?dbtype=odbc&dsn=DataSetName
các phương thức khác :
- getDriver()--cho biết driver hỗ trợ kết nối đến một URL cụ thể.
- registerDriver()--để drivers tự đăng kí với DriverManager.
- deregisterDriver()--để driver huỷ đăng kí.
- getLoginTimeout()--cho biết thời gian hạn định tối đa một drivers cố thử log in vào CSDL.
- setLoginTimeout()--thiết đặt thời gian hạn định tối đa trên.
- getLogStream()--cho biết stream dùng để logging.
- setLogStream()-- ấn định stream nói trên.
- println()--Viết dữ liệu vào log stream.
Driver Interface
Xây dựng một JDBC driver là một lớp để triển khai Driver interface. Các phương thức của Driver interface:
- connect()--thiết lập kết nối. DriverManager sẽ gọi nó để lập kết nối cho driver tương ứng.
- acceptsURL()--Cho biết driver có thể mở một kết nối CSDL qua URL đã cho hay không.
- getPropertyInfo()--Cho mảng DriverPropertyInfo cung cấp các thông tin về cách sử dụng driver để kết nối đến CSDL.
- getMajorVersion()--Cho số chính của version của driver.
- getMinorVersion()--Cho số phụ của version.
- jdbcCompliant()--cho biết driver có hoàn toàn tương hợp JDBC-compliant hay không.
Chương trình DriverApp
Chương trình DriverApp minh hoạ cách sử dụng các lớp DriverManager và DriverPropertyInfo và Driver interface.
Chương trình DriverApp .
import java.sql.*;
import java.util.*;
class DriverApp {
public static void main(String args[]) {
try{
// Load the database drivers
Class.forName("ids.sql.IDSDriver");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// Obtain a list of the loaded drivers
Enumeration drivers = DriverManager.getDrivers();
System.out.println("Available drivers:");
while(drivers.hasMoreElements()){
Driver driver=(Driver)drivers.nextElement();
// Display information about each driver
System.out.println(" Driver: "+driver.getClass().getName());
System.out.println(" Major version: "+driver.getMajorVersion());
System.out.println(" Minor version: "+driver.getMinorVersion());
System.out.println(" JDBC compliant: "+driver.jdbcCompliant());
// Get driver properties
DriverPropertyInfo props[] = driver.getPropertyInfo("",null);
if(props!=null){
// Display each property and its value
System.out.println(" Properties: ");
for(int i=0;i<props.length;++i){
System.out.println(" Name: "+props[i].name);
System.out.println(" Description: "+props[i].description);
System.out.println(" Value: "+props[i].value);
if(props[i].choices!=null){
System.out.println(" Choices: ");
for(int j=0;j<props[i].choices.length;++j)
System.out.println(" "+props[i].choices[j]);
}
System.out.println(" Required: "+props[i].required);
}
}
}
}catch(Exception ex){
System.out.println(ex);
System.exit(0);
}
}
}
Khi chạy chương trình, sẽ cho kết quả dạng như sau:
Available drivers:
Driver: ids.sql.IDSDriver
Major version: 2
Minor version: 5
JDBC compliant: true
Properties:
Name: dsn
Description: Data Source Name or Database Name
Value: null
Required: true
Name: user
Description: User ID
Value: null
Required: false
Name: password
Description: Password
Value: null
Required: false
Driver: sun.jdbc.odbc.JdbcOdbcDriver
Major version: 1
Minor version: 2001
JDBC compliant: true
Thiết lập kết nối đến CSDL
Connection Interface
getConnection() : kết nối đến CSDL
trả về một đối tượng với Connection interface.
Một số phương thức quan trọng :
- close()--đóng kết nối.
- getMetaData()--Trả về một DatabaseMetaData interface dùng để lấy các thông tin chi tiết về cấu trúc và khả năng của CSDL.
- createStatement()--Tạo một câu lệnh SQL.
- prepareStatement()--Tạo một đối tượng PreparedStatement SQL, từ một SQL string. PreparedStatement là một câu lệnh SQL tiền biên dịch, thực hiện hiệu qủa hơn.
- prepareCall()--Tạo một CallableStatement SQL từ SQL string.
Ta đã biết có 4 kiểu JDBC drivers:
- JDBC-ODBC bridge và ODBC driver
- Native-API partly Java driver
- JDBC-Net pure Java driver
- Native-protocol pure Java driver
Thiết lập ODBC Drivers để làm việc với CSDL Microsoft Access.
Các bước
Thiết đặt CSDL như một ODBC data source.
Control Panel, chạy 32-bit ODBC, chọn System DSN (Data Source Name), Add .
Gõ tên của tệp csdl ; Select để thiết đặt đường dẫn tới thư mục chứa tệp CSDL.
Nếu dùng IDS JDBC driver của IDS Software ( kiểu 3) cần đọc tài liệu hướng dẫn sử dụng.
Cần thêm đưòng dẫn vào CLASSPATH.
Chương trình AccessApp
Chương trình AccessApp
import java.awt.*;
import java.awt.event.*;
import java.sql.*;
public class AccessApp extends Frame {
TextField driver = new TextField(60);
TextField url = new TextField(60);
TextField sql = new TextField(60);
Button doIt = new Button("Do it!");
TextArea resultArea = new TextArea(10,60);
public static void main(String args[]){
AccessApp app = new AccessApp();
}
public AccessApp() {
super("AccessApp");
setup();
pack();
addWindowListener(new WindowEventHandler());
show();
}
void setup() {
setupMenuBar();
setLayout(new GridLayout(2,1));
Panel topPanel = new Panel();
topPanel.setLayout(new GridLayout(4,1));
Panel panels[]=new Panel[4];
for(int i=0;i<panels.length;++i){
panels[i]=new Panel();
panels[i].setLayout(new FlowLayout(FlowLayout.LEFT));
}
panels[0].add(new Label("Driver:"));
panels[0].add(driver);
panels[1].add(new Label("URL: "));
panels[1].add(url);
panels[2].add(new Label("SQL: "));
panels[2].add(sql);
doIt.addActionListener(new ButtonHandler());
panels[3].add(doIt);
for(int i=0;i<panels.length;++i)
topPanel.add(panels[i]);
add(topPanel);
add(resultArea);
}
void setupMenuBar() {
MenuBar menuBar = new MenuBar();
Menu fileMenu = new Menu("File");
MenuItem fileExit = new MenuItem("Exit");
fileExit.addActionListener(new MenuItemHandler());
fileMenu.add(fileExit);
menuBar.add(fileMenu);
setMenuBar(menuBar);
}
void accessDB() {
try{
// Load JDBC driver
Class.forName(driver.getText());
// Connect to database
Connection connection=DriverManager.getConnection(url.getText());
Statement statement = connection.createStatement();
// Execute SQL
boolean hasResults = statement.execute(sql.getText());
if(hasResults){
// Get results of query
ResultSet result = statement.getResultSet();
if(result!=null) displayResults(result);
}else resultArea.setText("");
// Close database connection
connection.close();
}catch(Exception ex){
resultArea.setText(ex.toString());
}
}
void displayResults(ResultSet r) throws SQLException {
ResultSetMetaData rmeta = r.getMetaData();
// Use meta data to obtain the number of columns
int numColumns=rmeta.getColumnCount();
String text="";
for(int i=1;i<=numColumns;++i) {
if(i<numColumns)
text+=rmeta.getColumnName(i)+" | ";
else
text+=rmeta.getColumnName(i);
}
text+=" ";
while(r.next()){
for(int i=1;i<=numColumns;++i) {
if(i<numColumns)
text+=r.getString(i)+" | ";
else
text+=r.getString(i).trim();
}
text+=" ";
}
resultArea.setText(text);
}
class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent ev){
String s=ev.getActionCommand();
if(s=="Do it!") accessDB();
}
}
class MenuItemHandler implements ActionListener {
public void actionPerformed(ActionEvent ev){
String s=ev.getActionCommand();
if(s=="Exit"){
System.exit(0);
}
}
}
class WindowEventHandler extends WindowAdapter {
public void windowClosing(WindowEvent e){
System.exit(0);
}
}
}
5.3 Sử dung chương trình AccessApp.
Trước khi chạy AccessApp cần khởi động IDS Server. AccessApp sẽ hiển thị cửa sổ cho phép gõ vào các input.
Trường Driver để nhập tên của JDBC driver.
Trường URL để nhập URL của CSDL .
Trường SQL để nhập câu lệnh SQL.
Dưới đây sẽ minh hoạ từng trường hợp cụ thể.
JDBC-ODBC bridge.
Driver này kèm liền trong bộ JDK 1.2.
1. TrườngDriver : gõ vào sun.jdbc.odbc.JdbcOdbcDriver nghĩa là dùng JDBC-ODBC bridge driver.
2. Trường URL : gõjdbc:odbc: <tên của Data source> .
3. TrườngSQL : gõ vào ví dụ SELECT * FROM <tên bảng csdl>
4. Nhấn nútDo it! .
chương trình sẽ liêt kê tào bộ nội dung của tệp.
Tương tự đối với trường hợp dùng IDS JDBC driver.
1. TrườngDriver : gõ vào ids.sql.IDSDriver nghĩa là dùng IDS driver.
2. Trường URL : gõ vàojdbc:ids://your.host.com:port/conn?dbtype=odbc&dsn=' tên của Data source' . IDS Server dùng cổng mặc định là 12.
3. TrườngSQL : gõ vào ví dụ SELECT * FROM <tên bảng csdl>
4. Nhấn nút Do it!.
Hoạt động của AccessApp
Đối tượng của lớp ButtonHandler xử lí nhấn nút Do it! Bằng cách gọi phương thức accessDB(). accessDB() gọi forName() để nạp JDBC driver có tên trong biến driver . ItSau đó nó gọi getConnection() của lớp DriverManager để lập kết nối đến CSDL trong URL đã cho.
Phương thức createStatement() của lớp Connection sẽ tạo câu lệnh.
Phương thức execute() sẽ cho thực hiện câu lệnh SQL đã nhập vào trong biến sql.
Phương thức getResultSet() dùng để lấy kết quả.
Phương thức displayResults() hiển thị kết quả.
Phương thức close() của Connection sẽ đóng kết nối.
Dùng java.sql với Applets
Applets có thể giao tiếp với CSDL sử dụng bất kì kiểu JDBC driver nào. Tuy nhiên hiệu quả phụ thuộc vào kiểu driver đã chọn. Có 4 kiểu như ta đã biết.
Các drivers kiểu 3 và 4 hỗ trợ applets với zero installation. Vì các JDBC drivers được viết hoàn toàn bằng Java, chúng được tải xuống từ Web server cùng với applet. Để hỗ trợ zero installation, các drivers phải đặt trên Web server trong cùng thư mục với applet.
Trusted vs. Untrusted Applets
Server CSDL và access server nằm ở đâu là rất quan trọng. Untrusted applets chỉ có thể truy cập host chứa nó, nghĩa là nó chỉ có thể trao đổi với Web server mà từ đó nó được tải về. Mục đích là hạn chế applets truy cập các thông tin nhậy cảm.
Khi sử dụng JDBC drivers kiểu 1, 2, hay 4, bạn phải đặt server CSDL trong cùng host với Web server. Điều này ảnh hương đến hiệu năng làm việc nếu Web site quá bận rộn. Nếu muốn nối đến các host khác trên Internet, phải yêu cầu NSD tin cậy -trust- applets của mình. Đây là một áp đặt đối với NSD.
Với driver kiểu 3, chỉ cần đặt database access server trên cùng host với Web server. Có thể đặt server CSDL trên máy khác. Điều này tăng hiệu quả đáng kể. Một số database access servers đã tích hợp sẵn với Web server và cùng chia sẻ cổng HTTP. Thêm nữa, một database access server riêng cho phép sử dụng nhiều servers CSDL nằm trên các hosts độc lập. Tóm lại drivers kiểu 3 cho giải pháp mềm dẻo và dễ dùng hơn.
Xử lý form và thâm nhập CSDL
Ta sẽ xây dựng một applet cho hiển thị một form và cập nhật CSDL theo các thông tin mà NSD gõ vào.
Khi cho chạy applet Survey dưới đây cần sửa lại input về JDBC driver và tên của host trong phương thức updateDatabase()
void updateDatabase(){
try{
Class.forName("-----------");
String url=" ---------------";
url+=" ------------------";
Connection connection=DriverManager.getConnection(url);
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.sql.*;
public class Survey extends Applet {
Label blankLine = new Label(" ");
TextField email = new TextField(50);
TextField name = new TextField(50);
Checkbox home = new Checkbox("I use Java at home.");
Checkbox school = new Checkbox("I use Java at school.");
Checkbox work = new Checkbox("I use Java at work.");
Checkbox jdk12 = new Checkbox("I use the JDK 1.2 or later.");
Checkbox standalone = new Checkbox("I develop standalone Java applications.");
Checkbox applets = new Checkbox("I develop Java applets.");
Checkbox database = new Checkbox("I develop database applications using Java.");
Checkbox rmi = new Checkbox("I use remote method invocation in my applications/applets.");
Checkbox intranet = new Checkbox("I use Java-based applications for the intranet.");
Checkbox internet = new Checkbox("I develop Java-based applications for the Internet.");
Button submitButton = new Button("Submit survey data.");
public void init() {
setLayout(new GridLayout(21,1));
Panel panels[]=new Panel[21];
for(int i=0;i<panels.length;++i){
panels[i]=new Panel();
panels[i].setLayout(new FlowLayout(FlowLayout.LEFT));
}
submitButton.addActionListener(new ButtonHandler());
panels[0].add(blankLine);
panels[1].add(new Label("Please provide your e-mail address and name (optional)."));
panels[2].add(blankLine);
panels[3].add(new Label("E-mail address:"));
panels[3].add(email);
panels[4].add(new Label("Name:"));
panels[4].add(name);
panels[5].add(blankLine);
panels[6].add(new Label("Please check all that apply."));
panels[7].add(blankLine);
panels[8].add(home);
panels[9].add(school);
panels[10].add(work);
panels[11].add(jdk12);
panels[12].add(standalone);
panels[13].add(applets);
panels[14].add(database);
panels[15].add(rmi);
panels[16].add(intranet);
panels[17].add(internet);
panels[18].add(blankLine);
panels[19].add(submitButton);
panels[20].add(blankLine);
for(int i=0;i<panels.length;++i) add(panels[i]);
}
void updateDatabase(){
try{
// Load IDS driver
Class.forName("ids.sql.IDSDriver");
String url="jdbc:ids://cx122974-a.cv1.sdca.home.com:80/";
url+="conn?dbtype=odbc&dsn='Survey'";
// Connect to database
Connection connection=DriverManager.getConnection(url);
Statement statement = connection.createStatement();
String sql="INSERT INTO RawData VALUES (`"+email.getText()+"'";
sql+=",'"+name.getText()+"'";
sql+=toDigit(home);
sql+=toDigit(school);
sql+=toDigit(work);
sql+=toDigit(jdk12);
sql+=toDigit(standalone);
sql+=toDigit(applets);
sql+=toDigit(database);
sql+=toDigit(rmi);
sql+=toDigit(intranet);
sql+=toDigit(internet);
sql+=")";
// Execute SQL
statement.executeUpdate(sql);
// Close database connection
connection.close();
displayPanel("Thank you!");
}catch(Exception ex){
displayPanel(ex.toString());
}
}
String toDigit(Checkbox ch){
boolean state = ch.getState();
if(state) return ",'1'";
else return ",'0'";
}
void displayPanel(String s){
removeAll();
setLayout(new BorderLayout());
Font currentFont = getFont();
setFont(new Font(currentFont.getName(),Font.ITALIC+Font.BOLD,18));
add("Center",new Label(s,Label.CENTER));
invalidate();
doLayout();
}
class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e){
String s = e.getActionCommand();
if("Submit survey data.".equals(s)){
updateDatabase();
}
}
}
}
Tệp survey.htm.
<HTML>
<HEAD>
<TITLE>Java Survey</TITLE>
</HEAD>
<BODY>
<APPLET CODE="Survey.class" WIDTH=550 HEIGHT=475>
[Survey applet]
</APPLET>
</BODY>
</HTML>
Hoạt động của Survey Applet
Phần lớn câu lệnh của Survey applet là để tạo form điều tra.
Khi nhấn nút Submit đối tượng ButtonHandler sẽ gọi phương thức updateDatabase() để cập nhật các thông tin từ form.
updateDatabase() nạp JDBC driver và thiết lập kết nối đến CSDL trong URL đã cho. Nó thực hiện câu lệnh "INSERT INTO RawData VALUE (...)" với các giá trị nhận từ form.
Phương thức toDigit() chuyển đổi các giá trị input từ các ô kiểm của form thành 0/1 theo đúng dạng của Microsoft Access.