下面羅列了各種數據庫使用JDBC連接的方式,可以作為一個手冊使用。

  1、Oracle8/8i/9i數據庫(thin模式)

  Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
  String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl為數據庫的SID
  String user="test";
  String password="test";
  Connection conn= DriverManager.getConnection(url,user,password);

  2、DB2數據庫

  Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
  String url="jdbc:db2://localhost:5000/sample"; //sample為你的數據庫
  String user="admin";
  String password="";
  Connection conn= DriverManager.getConnection(url,user,password);

  3、Sql Server7.0/2000數據庫

  Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
  String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
  //mydb為數據庫
  String user="sa";
  String password="";
  Connection conn= DriverManager.getConnection(url,user,password);

  4、Sybase數據庫

  Class.forName("com.sybase.jdbc.SybDriver").newInstance();
  String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB為你的數據庫
  Properties sysProps = System.getProperties();
  SysProps.put("user","userid");
  SysProps.put("password","user_password");
  Connection conn= DriverManager.getConnection(url, SysProps);

  5、Informix數據庫

  Class.forName("com.informix.jdbc.IfxDriver").newInstance();
  String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
  user=testuser;password=testpassword"; //myDB為數據庫
  Connection conn= DriverManager.getConnection(url);

  6、MySQL數據庫

  Class.forName("org.gjt.mm.mysql.Driver").newInstance();
  String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
  //myDB為數據庫
  Connection conn= DriverManager.getConnection(url);

  7、PostgreSQL數據庫

  Class.forName("org.postgresql.Driver").newInstance();
  String url ="jdbc:postgresql://localhost/myDB" //myDB為數據庫
  String user="myuser";
  String password="mypassword";
  Connection conn= DriverManager.getConnection(url,user,password);

  8、access數據庫直連用ODBC的

  Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
  String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
  Connection conn = DriverManager.getConnection(url,"","");
  Statement stmtNew=conn.createStatement() ;

  二、JDBC連接MySql方式

  下面是使用JDBC連接MySql的一個小的教程

  1、查找驅動程序

  MySQL目前提供的java驅動程序為Connection/J,可以從MySQL官方網站下載,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驅動程序為純java驅動程序,不需做其他配置。

  2、動態指定classpath

  如果需要執行時動態指定classpath,就在執行時采用-cp方式。否則將上面的.jar文件加入到classpath環境變量中。

  3、加載驅動程序

  try{
  Class.forName(com.mysql.jdbc.Driver);
  System.out.println(Success loading Mysql Driver!);
  }catch(Exception e)
  {
  System.out.println(Error loading Mysql Driver!);
  e.printStackTrace();
  }

  4、設置連接的url

  jdbc:mysql://localhost/databasename[?pa=va][&pa=va]

   三、以下列出了在使用JDBC來連接Oracle數據庫時可以使用的一些技巧

  1、在客戶端軟件開發中使用Thin驅動程序

  在開發Java軟件方面,Oracle的數據庫提供了四種類型的驅動程序,二種用于應用軟件、applets、servlets等客戶端軟件,另外二種用于數據庫中的Java存儲過程等服務器端軟件。在客戶機端軟件開發中,我們可以選擇OCI驅動程序或Thin驅動程序。OCI驅動程序利用Java本地化接口(JNI),通過Oracle客戶端軟件數據庫進行通訊。Thin驅動程序是純Java驅動程序,它直接與數據庫進行通訊。為了獲得最高的性能,Oracle建議在客戶端軟件開發中使用OCI驅動程序,這似乎是正確的。但我建議使用Thin驅動程序,因為通過多次測試發現,在通常情況下,Thin驅動程序的性能都超過了OCI驅動程序

  2、關閉自動提交功能,提高系統性能

  在第一次建立與數據庫的連接時,在缺省情況下,連接是在自動提交模式下的。為了獲得更好的性能,可以通過調用帶布爾值false參數的Connection類的setAutoCommit()方法關閉自動提交功能,如下所示:

  conn.setAutoCommit(false);

  值得注意的是,一旦關閉了自動提交功能,我們就需要通過調用Connection類的commit()和rollback()方法來人工的方式對事務進行管理

  3、在動態SQL或有時間限制的命令中使用Statement對象

  在執行SQL命令時,我們有二種選擇:可以使用PreparedStatement對象,也可以使用Statement對象。無論多少次地使用同一個SQL命令,PreparedStatement都只對它解析和編譯一次。當使用Statement對象時,每次執行一個SQL命令時,都會對它進行解析和編譯。這可能會使你認為,使用PreparedStatement對象比使用Statement對象的速度更快。然而,我進行的測試表明,在客戶端軟件中,情況并非如此。因此,在有時間限制的SQL操作中,除非成批地處理SQL命令,我們應當考慮使用Statement對象。

  此外,使用Statement對象也使得編寫動態SQL命令更加簡單,因為我們可以將字符串連接在一起,建立一個有效的SQL命令。因此,我認為,Statement對象可以使動態SQL命令的創建和執行變得更加簡單。

  4、利用helper函數對動態SQL命令進行格式化

  在創建使用Statement對象執行的動態SQL命令時,我們需要處理一些格式化方面的問題。例如,如果我們想創建一個將名字O'Reilly插入表中的SQL命令,則必須使用二個相連的“''”號替換O'Reilly中的“'”號。完成這些工作的最好的方法是創建一個完成替換操作的helper方法,然后在連接字符串心服用公式表達一個SQL命令時,使用創建的helper方法。與此類似的是,我們可以讓helper方法接受一個Date型的值,然后讓它輸出基于Oracle的to_date()函數的字符串表達式。

  5、利用PreparedStatement對象提高數據庫的總體效率

  在使用PreparedStatement對象執行SQL命令時,命令被數據庫進行解析和編譯,然后被放到命令緩沖區。然后,每當執行同一個PreparedStatement對象時,它就會被再解析一次,但不會被再次編譯。在緩沖區中可以發現預編譯的命令,并且可以重新使用。在有大量用戶的企業級應用軟件中,經常會重復執行相同的SQL命令,使用PreparedStatement對象帶來的編譯次數的減少能夠提高數據庫的總體性能。如果不是在客戶端創建、預備、執行PreparedStatement任務需要的時間長于Statement任務,我會建議在除動態SQL命令之外的所有情況下使用PreparedStatement對象。

  6、在成批處理重復的插入或更新操作中使用PreparedStatement對象

  如果成批地處理插入和更新操作,就能夠顯著地減少它們所需要的時間。Oracle提供的Statement和 CallableStatement并不真正地支持批處理,只有PreparedStatement對象才真正地支持批處理。我們可以使用addBatch()和executeBatch()方法選擇標準的JDBC批處理,或者通過利用PreparedStatement對象的setExecuteBatch()方法和標準的executeUpdate()方法選擇速度更快的Oracle專有的方法。要使用Oracle專有的批處理機制,可以以如下所示的方式調用setExecuteBatch():

  PreparedStatement pstmt3D null;
  try {
  ((OraclePreparedStatement)pstmt).setExecuteBatch(30);
  ...
  pstmt.executeUpdate();
  }

  調用setExecuteBatch()時指定的值是一個上限,當達到該值時,就會自動地引發SQL命令執行,標準的executeUpdate()方法就會被作為批處理送到數據庫中。我們可以通過調用PreparedStatement類的sendBatch()方法隨時傳輸批處理任務。

  7、使用Oracle locator方法插入、更新大對象(LOB)

  Oracle的PreparedStatement類不完全支持BLOB和CLOB等大對象的處理,尤其是Thin驅動程序不支持利用PreparedStatement對象的setObject()和setBinaryStream()方法設置BLOB的值,也不支持利用setCharacterStream()方法設置CLOB的值。只有locator本身中的方法才能夠從數據庫中獲取LOB類型的值。可以使用PreparedStatement對象插入或更新LOB,但需要使用locator才能獲取LOB的值。由于存在這二個問題,因此,我建議使用locator的方法來插入、更新或獲取LOB的值。

  8、使用SQL92語法調用存儲過程

  在調用存儲過程時,我們可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并沒有什么實際的好處,而且會給以后維護你的應用程序開發人員帶來麻煩,因此,我建議在調用存儲過程時使用SQL92。

  9、使用Object SQL將對象模式轉移到數據庫

  既然可以將Oracle的數據庫作為一種面向對象的數據庫來使用,就可以考慮將應用程序中的面向對象模式轉到數據庫中。目前的方法是創建Java bean作為偽裝的數據庫對象,將它們的屬性映射到關系表中,然后在這些bean中添加方法。盡管這樣作在Java中沒有什么問題,但由于操作都是在數據庫之外進行的,因此其他訪問數據庫的應用軟件無法利用對象模式。如果利用Oracle的面向對象的技術,可以通過創建一個新的數據庫對象類型在數據庫中模仿其數據和操作,然后使用JPublisher等工具生成自己的Java bean類。如果使用這種方式,不但Java應用程序可以使用應用軟件的對象模式,其他需要共享你的應用中的數據和操作的應用軟件也可以使用應用軟件中的對象模式。

  10、利用SQL完成數據庫內的操作

  我要向大家介紹的最重要的經驗是充分利用SQL的面向集合的方法來解決數據庫處理需求,而不是使用Java等過程化的編程語言。

  如果編程人員要在一個表中查找許多行,結果中的每個行都會查找其他表中的數據,最后,編程人員創建了獨立的UPDATE命令來成批地更新第一個表中的數據。與此類似的任務可以通過在set子句中使用多列子查詢而在一個UPDATE命令中完成。當能夠在單一的SQL命令中完成任務,何必要讓數據在網上流來流去的?我建議用戶認真學習如何最大限度地發揮SQL的功能。
           

CNBIE BLOG

JDBC連接數據庫經驗技巧集萃

原文:JDBC連接數據庫經驗技巧集萃
Java數據庫連接(JDBC)由一組用 Java 編程語言編寫的類和接口組成。JDBC 為工具/數據庫開發人員提供了一個標準的 API,使他們能夠用純Java API 來編寫數據庫應用程序。然而各個開發商的接口并不完全相同,所以開發環境的變化會帶來一定的配置變化。本文主要集合了不同數據庫的連接方式。

  一、連接各種數據庫方式速查表

  下面羅列了各種數據庫使用JDBC連接的方式,可以作為一個手冊使用。

  1、Oracle8/8i/9i數據庫(thin模式)

Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl為數據庫的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);

  2、DB2數據庫

Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sample為你的數據庫
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);

  3、Sql Server7.0/2000數據庫

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
//mydb為數據庫
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);

  4、Sybase數據庫

Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB為你的數據庫
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);

  5、Informix數據庫

Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB為數據庫
Connection conn= DriverManager.getConnection(url);

  6、MySQL數據庫

Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
//myDB為數據庫
Connection conn= DriverManager.getConnection(url);

  7、PostgreSQL數據庫

Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB" //myDB為數據庫
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);

  8、access數據庫直連用ODBC的

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;

  二、JDBC連接MySql方式

  下面是使用JDBC連接MySql的一個小的教程

  1、查找驅動程序

  MySQL目前提供的java驅動程序為Connection/J,可以從MySQL官方網站下載,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驅動程序為純java驅動程序,不需做其他配置。

  2、動態指定classpath

  如果需要執行時動態指定classpath,就在執行時采用-cp方式。否則將上面的.jar文件加入到classpath環境變量中。

  3、加載驅動程序

try{
 Class.forName(com.mysql.jdbc.Driver);
 System.out.println(Success loading Mysql Driver!);
}catch(Exception e)
{
 System.out.println(Error loading Mysql Driver!);
 e.printStackTrace();
}

  4、設置連接的url

jdbc:mysql://localhost/databasename[?pa=va][&pa=va]



  三、以下列出了在使用JDBC來連接Oracle數據庫時可以使用的一些技巧

  1、在客戶端軟件開發中使用Thin驅動程序

  在開發Java軟件方面,Oracle的數據庫提供了四種類型的驅動程序,二種用于應用軟件、applets、servlets等客戶端軟件,另外二種用于數據庫中的Java存儲過程等服務器端軟件。在客戶機端軟件開發中,我們可以選擇OCI驅動程序或Thin驅動程序。OCI驅動程序利用Java本地化接口(JNI),通過Oracle客戶端軟件數據庫進行通訊。Thin驅動程序是純Java驅動程序,它直接與數據庫進行通訊。為了獲得最高的性能,Oracle建議在客戶端軟件開發中使用OCI驅動程序,這似乎是正確的。但我建議使用Thin驅動程序,因為通過多次測試發現,在通常情況下,Thin驅動程序的性能都超過了OCI驅動程序

  2、關閉自動提交功能,提高系統性能

  在第一次建立與數據庫的連接時,在缺省情況下,連接是在自動提交模式下的。為了獲得更好的性能,可以通過調用帶布爾值false參數的Connection類的setAutoCommit()方法關閉自動提交功能,如下所示:

  conn.setAutoCommit(false);

  值得注意的是,一旦關閉了自動提交功能,我們就需要通過調用Connection類的commit()和rollback()方法來人工的方式對事務進行管理

  3、在動態SQL或有時間限制的命令中使用Statement對象

  在執行SQL命令時,我們有二種選擇:可以使用PreparedStatement對象,也可以使用Statement對象。無論多少次地使用同一個SQL命令,PreparedStatement都只對它解析和編譯一次。當使用Statement對象時,每次執行一個SQL命令時,都會對它進行解析和編譯。這可能會使你認為,使用PreparedStatement對象比使用Statement對象的速度更快。然而,我進行的測試表明,在客戶端軟件中,情況并非如此。因此,在有時間限制的SQL操作中,除非成批地處理SQL命令,我們應當考慮使用Statement對象。

  此外,使用Statement對象也使得編寫動態SQL命令更加簡單,因為我們可以將字符串連接在一起,建立一個有效的SQL命令。因此,我認為,Statement對象可以使動態SQL命令的創建和執行變得更加簡單。

  4、利用helper函數對動態SQL命令進行格式化

  在創建使用Statement對象執行的動態SQL命令時,我們需要處理一些格式化方面的問題。例如,如果我們想創建一個將名字O'Reilly插入表中的SQL命令,則必須使用二個相連的“''”號替換O'Reilly中的“'”號。完成這些工作的最好的方法是創建一個完成替換操作的helper方法,然后在連接字符串心服用公式表達一個SQL命令時,使用創建的helper方法。與此類似的是,我們可以讓helper方法接受一個Date型的值,然后讓它輸出基于Oracle的to_date()函數的字符串表達式。

  5、利用PreparedStatement對象提高數據庫的總體效率

  在使用PreparedStatement對象執行SQL命令時,命令被數據庫進行解析和編譯,然后被放到命令緩沖區。然后,每當執行同一個PreparedStatement對象時,它就會被再解析一次,但不會被再次編譯。在緩沖區中可以發現預編譯的命令,并且可以重新使用。在有大量用戶的企業級應用軟件中,經常會重復執行相同的SQL命令,使用PreparedStatement對象帶來的編譯次數的減少能夠提高數據庫的總體性能。如果不是在客戶端創建、預備、執行PreparedStatement任務需要的時間長于Statement任務,我會建議在除動態SQL命令之外的所有情況下使用PreparedStatement對象。

  6、在成批處理重復的插入或更新操作中使用PreparedStatement對象

  如果成批地處理插入和更新操作,就能夠顯著地減少它們所需要的時間。Oracle提供的Statement和 CallableStatement并不真正地支持批處理,只有PreparedStatement對象才真正地支持批處理。我們可以使用addBatch()和executeBatch()方法選擇標準的JDBC批處理,或者通過利用PreparedStatement對象的setExecuteBatch()方法和標準的executeUpdate()方法選擇速度更快的Oracle專有的方法。要使用Oracle專有的批處理機制,可以以如下所示的方式調用setExecuteBatch():

PreparedStatement pstmt3D null;
try {
 ((OraclePreparedStatement)pstmt).setExecuteBatch(30);
 ...
 pstmt.executeUpdate();
}

  調用setExecuteBatch()時指定的值是一個上限,當達到該值時,就會自動地引發SQL命令執行,標準的executeUpdate()方法就會被作為批處理送到數據庫中。我們可以通過調用PreparedStatement類的sendBatch()方法隨時傳輸批處理任務。

  7、使用Oracle locator方法插入、更新大對象(LOB)

  Oracle的PreparedStatement類不完全支持BLOB和CLOB等大對象的處理,尤其是Thin驅動程序不支持利用PreparedStatement對象的setObject()和setBinaryStream()方法設置BLOB的值,也不支持利用setCharacterStream()方法設置CLOB的值。只有locator本身中的方法才能夠從數據庫中獲取LOB類型的值。可以使用PreparedStatement對象插入或更新LOB,但需要使用locator才能獲取LOB的值。由于存在這二個問題,因此,我建議使用locator的方法來插入、更新或獲取LOB的值。

  8、使用SQL92語法調用存儲過程

  在調用存儲過程時,我們可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并沒有什么實際的好處,而且會給以后維護你的應用程序開發人員帶來麻煩,因此,我建議在調用存儲過程時使用SQL92。

  9、使用Object SQL將對象模式轉移到數據庫

  既然可以將Oracle的數據庫作為一種面向對象的數據庫來使用,就可以考慮將應用程序中的面向對象模式轉到數據庫中。目前的方法是創建Java bean作為偽裝的數據庫對象,將它們的屬性映射到關系表中,然后在這些bean中添加方法。盡管這樣作在Java中沒有什么問題,但由于操作都是在數據庫之外進行的,因此其他訪問數據庫的應用軟件無法利用對象模式。如果利用Oracle的面向對象的技術,可以通過創建一個新的數據庫對象類型在數據庫中模仿其數據和操作,然后使用JPublisher等工具生成自己的Java bean類。如果使用這種方式,不但Java應用程序可以使用應用軟件的對象模式,其他需要共享你的應用中的數據和操作的應用軟件也可以使用應用軟件中的對象模式。

  10、利用SQL完成數據庫內的操作

  我要向大家介紹的最重要的經驗是充分利用SQL的面向集合的方法來解決數據庫處理需求,而不是使用Java等過程化的編程語言。

  如果編程人員要在一個表中查找許多行,結果中的每個行都會查找其他表中的數據,最后,編程人員創建了獨立的UPDATE命令來成批地更新第一個表中的數據。與此類似的任務可以通過在set子句中使用多列子查詢而在一個UPDATE命令中完成。當能夠在單一的SQL命令中完成任務,何必要讓數據在網上流來流去的?我建議用戶認真學習如何最大限度地發揮SQL的功能。


CNBIE BLOG

JDBC鏈接sqlserver數據庫遇到的問題和解決方法

原文:JDBC鏈接sqlserver數據庫遇到的問題和解決方法

兩天的時間全都耗在這里了,其實這并不是很復雜的事情但還是把我搞了半天.



  • 首先是下載jdbc sql server 驅動.
  • 然后是將mssqlserver.jar,msbase.jar,msutil.jar考到tomcat/common/lib 下
    這里出現了問題.因為使用JCreater.沒有把這三個文件設置到JCreater調用的類庫里所以在使用是就沒有了提示.

  • 這次耗費時間的主要原因是沒有考慮到系統的問題.我的SQL Server是老早的一個版本了.所以安裝好后一直有問題.最后打上了sp3的布丁.總于搞定了.由此也得出一些結論,加上在這里問題種收集的一些資料最后匯集起來:
    1當出現“Error establishing socket“首先要確認sqlserver是否安裝了sp3的布丁

    2檢查SQL SERVER 是否允許遠程訪問.具體步驟:
    1)打開"企業管理器",打開控制臺根目錄>SQL Server 組>數據庫
    2)在相應"數據庫"上單擊右鍵,選擇"屬性"
    3)選擇"連接"選項卡,檢查"遠程服務器連接"下,RPC服務是否選擇.

    3使用telnet IP地址 1433,系統是否提示連接出錯,如系統提示出錯
    檢查是否防火墻屏蔽了SQL SERVER 或 java IDE 的網絡訪問端口
    如果是,關閉防火墻,重新啟動SQL SERVER和java IDE,進行測試,
    如果系統仍提示上述錯誤,嘗試下列步驟

    4檢查SQL SERVER 端口號及是否啟用了TCP/IP協議,具體步驟:
    1)打開"企業管理器",打開控制臺根目錄>SQL Server 組>數據庫
    2)在相應"數據庫"上單擊右鍵,選擇"屬性"
    3)選擇"常規"選項卡,點擊"網絡配置",如啟用的協議中無"TCP/IP協議"將其加入
    4)選擇"TCP/IP協議",點擊"屬性",檢查其端口號是否為1433
    5)如端口號為1433將其修改為其它端口號,修改jdbc連接語句,將端口號同樣改為新啟用的端口號,如jdbc:microsoft:sqlserver://server_name:1400(假設新端口號為 1400)





CNBIE BLOG

JDBC入門

原文:JDBC入門
JDBC 入門 -- 建立聯接
教程:JDBC 入門 作者:Maydene Fisher 翻譯:comer
  你需要做的第一事情是你與想要使用的 DBMS 建立一個連接。這包含 2 個步驟:裝載驅動程序并建立連接。

裝載驅動程序
  裝載驅動程序只需要非常簡單的一行代碼。例如,你想要使用 JDBC-ODBC 橋驅動程序, 可以用下列代碼裝載它:

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

  你的驅動程序文檔將告訴你應該使用的類名。例如, 如果類名是 jdbc.DriverXYZ ,你將用代碼以下的代碼裝載驅動程序

    Class.forName("jdbc.DriverXYZ");

  你不需要創建一個驅動程序類的實例并且用 DriverManager 登記它,因為調用 Class.forName 將自動將加載驅動程序類。如果你曾自己創建實例,你將創建一個不必要的副本,但它不會帶來什么壞處。

  加載 Driver 類后,它們即可用來與數據庫建立連接。

建立連接
  第二步就是用適當的驅動程序類與 DBMS 建立一個連接。下列代碼是一般的做法:

    Connection con = DriverManager.getConnection(url, "myLogin", "myPassword");

  這個步驟也非常簡單,最難的是怎么提供 url。如果你正在使用 JDBC-ODBC 橋, JDBC URL 將以 jdbc:odbc 開始:余下 URL 通常是你的數據源名字或數據庫系統。因此,假設你正在使用 ODBC 存取一個叫 "Fred" 的 ODBC 數據源,你的 JDBC URL 是 jdbc:odbc:Fred 。把 "myLogin" 及 "myPassword" 替換為你登陸 DBMS 的用戶名及口令。如果你登陸數據庫系統的用戶名為 "Fernanda" 口令為 "J8",只需下面的 2 行代碼就可以建立一個連接:

String url = "jdbc:odbc:Fred";
Connection con = DriverManager.getConnection(url,"Fernanda", "J8");
  如果你使用的是第三方開發了的 JDBC驅動程序,文檔將告訴你該使用什么 subprotocol, 就是在 JDBC URL 中放在 jdbc 后面的部分。例如, 如果驅動程序開發者注冊了 acme 作為 subprotocol, JDBC URL 的第一和第二部分將是 jdbc:acme。驅動程序文檔也會告訴你余下 JDBC URL 的格式。JDBC URL 最后一部分提供了定位數據庫的信息。

  如果你裝載的驅動程序識別了提供給 DriverManager.getConnection 的 JDBC URL ,那個驅動程序將根據 JDBC URL 建立一個到指定 DBMS 的連接。正如名稱所示,DriverManager 類在幕后為你管理建立連接的所有細節。除非你是正在寫驅動程序,你可能無需使用此類的其它任何方法,一般程序員需要在此類中直接使用的唯一方法是 DriverManager.getConnection。

  DriverManager.getConnection 方法返回一個打開的連接,你可以使用此連接創建 JDBC statements 并發送 SQL 語句到數據庫。在前面的例子里,con 對象是一個打開的連接,并且我們要在以后的例子里使用它。

JDBC 入門 -- 設置表
創建表
  首先,我們在我們的示例數據庫創建其中一張表 COFFEES,包含在咖啡店所賣咖啡的必要的信息,包括咖啡名字,他們的價格,本星期賣了多少磅及迄今為止賣的數目。關于 COFFEES 表我們以后會詳細描述,如下:

COF_NAME SUP_ID PRICE SALES TOTAL
Colombian 101 7.99 0 0
French_Roast 49 8.99 0 0
Espresso 150 9.99 0 0
Colombian_Decaf 101 8.99 0 0
French_Roast_Decaf 49 9.99 0 0

  存儲咖啡名的列是 COF_NAME,它的 SQL 數據類型是 VARCHAR,最大的長度為 32 個字符。因為我們所賣的每種類型咖啡都使用不同的名字,名字可用于作為唯一識別咖啡的標識,因此可用于作主鍵。第二個列叫 SUP_ID,用于保存咖啡供應商標識;其 SQL 數據類型為 INTEGER。第 3 列叫 PRICE,因為它需要保存帶小數的十進制數,因此它的 SQL 類型為 FLOAT。(注意,通常錢的 SQL 類型為 DECIMAL 或 NUMERIC,但在不同 DBMSs 間存在差異,為了避免于老版本的 JDBC 的不兼容性在本教程我們采用更標準的 FLOAT 類型)SALES 列的 SQL 類型為 INTEGER,其值為本星期所賣咖啡的磅數。最后一列,TOTAL 的 SQL 類型為 INTEGER,保存了迄今為止所賣咖啡的總磅數。

  數據庫里的第二個表 SUPPLIERS,保存了每個供應商的信息:

SUP_ID SUP_NAME STREET CITY STATE ZIP
101 Acme, Inc. 99 Market Street Groundsville CA 95199
49 Superior Coffee 1 Party Place Mendocino CA 95460
150 The High Ground 100 Coffee Lane Meadows CA 93966

  COFFEES 跟 SUPPLIERS 都包含列 SUP_ID,它意味著可以用 SELECT 語句從這兩張表中取得有關信息。列 SUP_ID 是 SUPPLIERS 表的主鍵,用于唯一識別每個咖啡供應商。在 COFFEES 表中,SUP_ID 列被稱外鍵。注意每個 SUP_ID 值在 SUPPLIERS 表里只出現一次;這對主鍵是必須的。在 COFFEES 表里,它作為外鍵,顯然它可以有重復的 SUP_ID 值,因為同一供應商可以提供很多種的咖啡。在本節的最后,你將看見如何在 SELECT 語句中使用主鍵及外鍵的一個例子。

  下面的 SQL 語句用于創建 COFFEES 表。列由列名跟空格跟 SQL 類型組成。列(包括列名及其 SQL 類型)跟下一個之間用逗號分隔。VARCHAR 類型創建定義了最大長度, 因此它需要有一個參數來表示最大長度。參數必須在類型后面的括號內。SQL 語句如下,列 COF_NAME 的長度 被限定為不得超過 32 個字符:

CREATE TABLE COFFEES
(COF_NAME VARCHAR(32),
SUP_ID INTEGER,
PRICE FLOAT,
SALES INTEGER,
TOTAL INTEGER)

  這些代碼不帶 DBMS 語句結束符, 因為每個 DBMS 都可能不同。例如, Oracle 使用一個分號 (;) 作為語句的結束,而 Sybase 使用 go。你所使用的驅動程序會自動提供合適的語句結束符,因此你無須把它包括在你的 JDBC 代碼中。

  另外,我們應該指出的的是 SQL 語句的格式。在 CREATE TABLE 語句中,關鍵字采用大寫字符,并且每個項目都另起一行。SQL 并沒有此要求;僅僅是為了更容易閱讀。SQL 標準是不區分關鍵詞的大小寫的, 因此,如下例中的 SELECT 語句可以有多種寫法。因此下面兩個不同寫法的語句對 SQL 來說是一樣的。

SELECT First_Name, Last_Name
FROM Employees
WHERE Last_Name LIKE "Washington"

select First_Name, Last_Name from Employees where
Last_Name like "Washington"

  然而,引號里的內容是區分大小寫的:在名字"Washington" 里 "W" 必須被大寫,并且余下的字符必須是小寫的。

  對于標識,不同的 DBMS 有不同的要求,例如, 某些 DBMSs 要求那些列名及表名必須跟創建時的一樣,有些則沒有此要求。為安全起見,我們全部使用大寫標識如 COFFEES、SUPPLIERS,因為我們是那樣定義他們的。

  到止我們寫了創建 COFFEES 表的 SQL 語句。現在我們在它外面加上引號(使它成為字符串),并且字符串賦值給變量 createTableCoffees,在以后的 JDBC 代碼中我們可以使用此變量。正如看到的,DBMS 并不在意分行,但對 Java 語言來,String 對象分行是通不過編譯的。因而,我們可以用加號 (+) 把每一行的串連接。

String createTableCoffees = "CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
"SALES INTEGER, TOTAL INTEGER)";

  我們在 CREATE TABLE 語句中使用的數據類型是通用的 SQL 類型(也稱 JDBC 類型)它們在類 java.sql.Types 中定義。DBMSs 通常使用這些標準的類型,因此,當你要嘗試一些 JDBC 應用程序時,你可以直接使用 CreateCoffees.java 應用程序,它使用了 CREATE TABLE 語句。如果你的 DBMS 使用了它的自己的本地的類型名字,我們為你供應其它的應用程序,我們將在后面詳細解釋。

  在運用任何應用程序前,當然,我們將讓你了解 JDBC 的基礎。

創建 JDBC Statements 對象
  Statement 對象用于把 SQL 語句發送到 DBMS 。你只須簡單地創建一個 Statement 對象并且然后執行它,使用適當的方法執行你發送的 SQL 語句。對 SELECT 語句來說,可以使用 executeQuery。要創建或修改表的語句,使用的方法是 executeUpdate。

  需要一個活躍的連接的來創建 Statement 對象的實例。在下面的例子中,我們使用我們的 Connection 對象 con 創建 Statement 對象 stmt:

Statement stmt = con.createStatement();

  到此 stmt 已經存在了,但它還沒有把 SQL 語句傳遞到 DBMS。我們需要提供 SQL 語句作為參數提供給我們使用的 Statement 的方法。例如,在下面的代碼段里,我們使用上面例子中的 SQL 語句作為 executeUpdate 的參數:

stmt.executeUpdate("CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
"SALES INTEGER, TOTAL INTEGER)");

  因為我們已經把 SQL 語句賦給了 createTableCoffees 變量,我們可以如下方式書寫代碼:

stmt.executeUpdate(createTableCoffees);

執行語句
  我們使用 executeUpdate 方法是因為在 createTableCoffees 中的 SQL 語句是 DDL (數據定義語言)語句。創建表,改變表,刪除表都是 DDL 語句的例子,要用 executeUpdate 方法來執行。你也可以從它的名字里看出,方法 executeUpdate 也被用于執行更新表 SQL 語句。實際上,相對于創建表來說,executeUpdate 用于更新表的時間更多,因為表只需要創建一次,但經常被更新。

  被使用最多的執行 SQL 語句的方法是 executeQuery。這個方法被用來執行 SELECT 語句,它幾乎是使用最多的 SQL 語句。馬上你將看到如何使用這個方法。

在表中輸入數據
  我們已經顯示了如何通過指定列名、數據類型來創建表 COFFEES,但是這僅僅建立表的結構。表還沒有任何數據。我們將次輸入一行數據到表中,提供每列的信息,注意插入的數據顯示順序跟表創建時候是一樣的,既缺省順序。

  下列代碼插入一個行數據,COF_NAME 的值為 Colombian,SUP_ID 為 101,PRICE 為 7.99,SALES 0,TOTAL 0。就象創建 COFFEES 表一樣,我們創建一 Statement 對象,并執行 executeUpdate 方法。

  因為 SQL 語句一行顯示不下,因此我們把它分為兩行,并用加號 (+) 相連。特別要注意的是,在 COFFEES 和 VALUES 之間要有空格。這個空格必須在引號之內并且要在 COFFEES 跟 VALUES 之間;沒有這個空格,SQL 語句將被錯誤地被讀作為 "INSERT INTO COFFEESVALUES ...",并且 DBMS 將尋找表 COFFEESVALUES。還要注意的是在 coffee name 上我們使用了單引號。

Statement stmt = con.createStatement();
stmt.executeUpdate(
"INSERT INTO COFFEES " +
"VALUES ('Colombian', 101, 7.99, 0, 0)");

  下面的代碼把第二行插入到表 COFFEES 中。我們可以在使用 Statement 對象而無須為每次執行創建一個新的。

stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('French_Roast', 49, 8.99, 0, 0)");

  剩下行的數據如下:

stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('Espresso', 150, 9.99, 0, 0)");
stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)");
stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)");

從表中取得數據
  既然表 COFFEES 中已經有數據了,我們就可以寫一個 SELECT 語句來取得這些值。下面的 SQL 語句中星號 (*) 表示選擇所有的列。因為沒有用 WHERE 子句來限制所選的行,因此下面的 SQL 語句選擇的是整個表。

SELECT * FROM COFFEES

  結果是整個表的數據,如下:

COF_NAME SUP_ID PRICE SALES TOTAL
--------------- ------ ----- ----- -----
Colombian 101 7.99 0 0
French_Roast 49 8.99 0 0
Espresso 150 9.99 0 0
Colombian_Decaf 101 8.99 0 0
French_Roast_Decaf 49 9.99 0 0

  如果你直接在數據庫系統里輸入 SQL 查詢語句,你將在你的終端上看到如上的結果。當我們通過一個 Java 應用程序存取一個數據庫時,正如我們馬上要做的一樣,我們需要檢索結果以便我們能使用他們。你將在下一節看到如何實現。

這是 SELECT 語句的另一個例子,這將得到咖啡及其各自每磅單價的列表。

SELECT COF_NAME, PRICE FROM COFFEES

查詢的結果集將具有如下形式:

COF_NAME PRICE
-------- ---------- -----
Colombian 7.99
French_Roast 8.99
Espresso 9.99
Colombian_Decaf 8.99
French_Roast_Decaf 9.99

上面 SELECT 語句取得了所有咖啡的名字及價格。而下面的 SELECT 語句限制那些每磅價格低于 $9.00 的咖啡才被選擇。
SELECT COF_NAME, PRICE
FROM COFFEES
WHERE PRICE < 9.00

結果集將具有如下形式:

COF_NAME PRICE
-------- ------- -----
Colombian 7.99
French_Roast 8.99
Colombian Decaf 8.99

JDBC 入門 -- 開始
你需要做的第一事情是你要正確的安裝。這包含下列幾個步驟:

在你的計算機上安裝 Java 和 JDBC
  Java 數據庫連接 (JDBC) 是一個標準 SQL(Structured Query Language,結構化查詢語言)數據庫訪問接口, 可以為多種關系數據庫提供統一訪問。JDBC(Java DataBase Connection,Java 數據庫連接) 也提供一種基準,據此可以構建更高級的工具和接口。 目前的 JDK(Java Development Kit,Java 開發工具包)軟件捆綁包括 JDBC 和 JDBC-ODBC(Open DataBase Connection,開放式數據庫連接)橋。這些包也可獨立得到,以跟 JDK 1.0 一起使用。應該注意的是,本文的示例使用了 JDBC 2.0 接口,需要 JDK 2.0 來運行,不能在 JDK 1.1 下運行。

  你可以從 http://java.sun.com/products/JDK/CurrentRelease 找到最新版。

安裝驅動程序
  你的驅動程序應該有安裝方法。為特定的 DBMSs 寫的 JDBC 驅動程序安裝時只要拷貝到你的計算機上就可以了。并不需要特殊的配置。

  如果你下載的是 Solaris 或 Windows JDK1.1 版本,橋作為包 sun.jdbc.odbc 與 JDK 一起自動安裝。有關安裝和配置 ODBC 的信息,請咨詢 ODBC 驅動程序廠商。橋無須特殊配置。有關客戶機安裝和配置信息,請咨詢數據庫廠商。

如果需要,安裝數據庫系統
  如果你不能確認是否安裝了數據庫系統,你需要按照供應商的要求安裝數據庫。大多數用戶都已經安裝了數據庫,可繼續使用他們安裝好的數據庫

配置數據庫
  我們假設數據庫 COFFEEBREAK 已經存在。(創建一個數據庫并不困難,但需要一定的權限并通常是由數據庫管理員來做)你還需要在此數據庫里創建本教程作為例子使用的表。我們有意限制表的大小跟及數目,以便于管理

  假設我們的數據庫是在一個咖啡館里使用, 咖啡豆按磅賣,而咖啡則以杯為單位。為了簡單起見,還假定經營者只需要 2 張表,分別存放不同種類的咖啡及咖啡供應商的有關信息。

  首先我們演示怎么打開一個 DBMS 連接, 及 JDBC 是怎么發送 SQL 語句到你的 DBMS。通過這些代碼,我們將表明使用 JDBC 傳遞 SQL 語句到你的 DBMS 并處理返回的結果是非常簡單的。

  所有的代碼在主要的幾個 DBMS 產品做了測試。然而, 如果你使用 JDBC-ODBC 橋來連接舊版本 ODBC 驅動程序時,可能會遇到一些兼容性問題。 


CNBIE BLOG

JDBC入門(三)-設置表

原文:JDBC入門(三)-設置表
作者:axeon
創建表
  首先,我們在我們的示例數據庫創建其中一張表 COFFEES,包含在咖啡店所賣咖啡的必要的信息,包括咖啡名字,他們的價格,本星期賣了多少磅及迄今為止賣的數目。關于 COFFEES 表我們以后會詳細描述,如下:

COF_NAME SUP_ID PRICE SALES TOTAL
Colombian 101 7.99 0 0
French_Roast 49 8.99 0 0
Espresso 150 9.99 0 0
Colombian_Decaf 101 8.99 0 0
French_Roast_Decaf 49 9.99 0 0

  存儲咖啡名的列是 COF_NAME,它的 SQL 數據類型是 VARCHAR,最大的長度為 32 個字符。因為我們所賣的每種類型咖啡都使用不同的名字,名字可用于作為唯一識別咖啡的標識,因此可用于作主鍵。第二個列叫 SUP_ID,用于保存咖啡供應商標識;其 SQL 數據類型為 INTEGER。第 3 列叫 PRICE,因為它需要保存帶小數的十進制數,因此它的 SQL 類型為 FLOAT。(注意,通常錢的 SQL 類型為 DECIMAL 或 NUMERIC,但在不同 DBMSs 間存在差異,為了避免于老版本的 JDBC 的不兼容性在本教程我們采用更標準的 FLOAT 類型)SALES 列的 SQL 類型為 INTEGER,其值為本星期所賣咖啡的磅數。最后一列,TOTAL 的 SQL 類型為 INTEGER,保存了迄今為止所賣咖啡的總磅數。

  數據庫里的第二個表 SUPPLIERS,保存了每個供應商的信息:

SUP_ID SUP_NAME STREET CITY STATE ZIP
101 Acme, Inc. 99 Market Street Groundsville CA 95199
49 Superior Coffee 1 Party Place Mendocino CA 95460
150 The High Ground 100 Coffee Lane Meadows CA 93966

  COFFEES 跟 SUPPLIERS 都包含列 SUP_ID,它意味著可以用 SELECT 語句從這兩張表中取得有關信息。列 SUP_ID 是 SUPPLIERS 表的主鍵,用于唯一識別每個咖啡供應商。在 COFFEES 表中,SUP_ID 列被稱外鍵。注意每個 SUP_ID 值在 SUPPLIERS 表里只出現一次;這對主鍵是必須的。在 COFFEES 表里,它作為外鍵,顯然它可以有重復的 SUP_ID 值,因為同一供應商可以提供很多種的咖啡。在本節的最后,你將看見如何在 SELECT 語句中使用主鍵及外鍵的一個例子。

  下面的 SQL 語句用于創建 COFFEES 表。列由列名跟空格跟 SQL 類型組成。列(包括列名及其 SQL 類型)跟下一個之間用逗號分隔。VARCHAR 類型創建定義了最大長度, 因此它需要有一個參數來表示最大長度。參數必須在類型后面的括號內。SQL 語句如下,列 COF_NAME 的長度 被限定為不得超過 32 個字符:

CREATE TABLE COFFEES
(COF_NAME VARCHAR(32),
SUP_ID INTEGER,
PRICE FLOAT,
SALES INTEGER,
TOTAL INTEGER)

  這些代碼不帶 DBMS 語句結束符, 因為每個 DBMS 都可能不同。例如, Oracle 使用一個分號 (;) 作為語句的結束,而 Sybase 使用 go。你所使用的驅動程序會自動提供合適的語句結束符,因此你無須把它包括在你的 JDBC 代碼中。

  另外,我們應該指出的的是 SQL 語句的格式。在 CREATE TABLE 語句中,關鍵字采用大寫字符,并且每個項目都另起一行。SQL 并沒有此要求;僅僅是為了更容易閱讀。SQL 標準是不區分關鍵詞的大小寫的, 因此,如下例中的 SELECT 語句可以有多種寫法。因此下面兩個不同寫法的語句對 SQL 來說是一樣的。

SELECT First_Name, Last_Name
FROM Employees
WHERE Last_Name LIKE "Washington"

select First_Name, Last_Name from Employees where
Last_Name like "Washington"

  然而,引號里的內容是區分大小寫的:在名字"Washington" 里 "W" 必須被大寫,并且余下的字符必須是小寫的。

  對于標識,不同的 DBMS 有不同的要求,例如, 某些 DBMSs 要求那些列名及表名必須跟創建時的一樣,有些則沒有此要求。為安全起見,我們全部使用大寫標識如 COFFEES、SUPPLIERS,因為我們是那樣定義他們的。

  到止我們寫了創建 COFFEES 表的 SQL 語句。現在我們在它外面加上引號(使它成為字符串),并且字符串賦值給變量 createTableCoffees,在以后的 JDBC 代碼中我們可以使用此變量。正如看到的,DBMS 并不在意分行,但對 Java 語言來,String 對象分行是通不過編譯的。因而,我們可以用加號 (+) 把每一行的串連接。

String createTableCoffees = "CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
"SALES INTEGER, TOTAL INTEGER)";

  我們在 CREATE TABLE 語句中使用的數據類型是通用的 SQL 類型(也稱 JDBC 類型)它們在類 java.sql.Types 中定義。DBMSs 通常使用這些標準的類型,因此,當你要嘗試一些 JDBC 應用程序時,你可以直接使用 CreateCoffees.java 應用程序,它使用了 CREATE TABLE 語句。如果你的 DBMS 使用了它的自己的本地的類型名字,我們為你供應其它的應用程序,我們將在后面詳細解釋。

  在運用任何應用程序前,當然,我們將讓你了解 JDBC 的基礎。

創建 JDBC Statements 對象
  Statement 對象用于把 SQL 語句發送到 DBMS 。你只須簡單地創建一個 Statement 對象并且然后執行它,使用適當的方法執行你發送的 SQL 語句。對 SELECT 語句來說,可以使用 executeQuery。要創建或修改表的語句,使用的方法是 executeUpdate。

  需要一個活躍的連接的來創建 Statement 對象的實例。在下面的例子中,我們使用我們的 Connection 對象 con 創建 Statement 對象 stmt:

Statement stmt = con.createStatement();

  到此 stmt 已經存在了,但它還沒有把 SQL 語句傳遞到 DBMS。我們需要提供 SQL 語句作為參數提供給我們使用的 Statement 的方法。例如,在下面的代碼段里,我們使用上面例子中的 SQL 語句作為 executeUpdate 的參數:

stmt.executeUpdate("CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
"SALES INTEGER, TOTAL INTEGER)");

  因為我們已經把 SQL 語句賦給了 createTableCoffees 變量,我們可以如下方式書寫代碼:

stmt.executeUpdate(createTableCoffees);

執行語句
  我們使用 executeUpdate 方法是因為在 createTableCoffees 中的 SQL 語句是 DDL (數據定義語言)語句。創建表,改變表,刪除表都是 DDL 語句的例子,要用 executeUpdate 方法來執行。你也可以從它的名字里看出,方法 executeUpdate 也被用于執行更新表 SQL 語句。實際上,相對于創建表來說,executeUpdate 用于更新表的時間更多,因為表只需要創建一次,但經常被更新。

  被使用最多的執行 SQL 語句的方法是 executeQuery。這個方法被用來執行 SELECT 語句,它幾乎是使用最多的 SQL 語句。馬上你將看到如何使用這個方法。

在表中輸入數據
  我們已經顯示了如何通過指定列名、數據類型來創建表 COFFEES,但是這僅僅建立表的結構。表還沒有任何數據。我們將次輸入一行數據到表中,提供每列的信息,注意插入的數據顯示順序跟表創建時候是一樣的,既缺省順序。

  下列代碼插入一個行數據,COF_NAME 的值為 Colombian,SUP_ID 為 101,PRICE 為 7.99,SALES 0,TOTAL 0。就象創建 COFFEES 表一樣,我們創建一 Statement 對象,并執行 executeUpdate 方法。

  因為 SQL 語句一行顯示不下,因此我們把它分為兩行,并用加號 (+) 相連。特別要注意的是,在 COFFEES 和 VALUES 之間要有空格。這個空格必須在引號之內并且要在 COFFEES 跟 VALUES 之間;沒有這個空格,SQL 語句將被錯誤地被讀作為 "INSERT INTO COFFEESVALUES ...",并且 DBMS 將尋找表 COFFEESVALUES。還要注意的是在 coffee name 上我們使用了單引號。

Statement stmt = con.createStatement();
stmt.executeUpdate(
"INSERT INTO COFFEES " +
"VALUES ('Colombian', 101, 7.99, 0, 0)");

  下面的代碼把第二行插入到表 COFFEES 中。我們可以在使用 Statement 對象而無須為每次執行創建一個新的。

stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('French_Roast', 49, 8.99, 0, 0)");

  剩下行的數據如下:

stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('Espresso', 150, 9.99, 0, 0)");
stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)");
stmt.executeUpdate("INSERT INTO COFFEES " +
"VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)");

從表中取得數據
  既然表 COFFEES 中已經有數據了,我們就可以寫一個 SELECT 語句來取得這些值。下面的 SQL 語句中星號 (*) 表示選擇所有的列。因為沒有用 WHERE 子句來限制所選的行,因此下面的 SQL 語句選擇的是整個表。

SELECT * FROM COFFEES

  結果是整個表的數據,如下:

COF_NAME SUP_ID PRICE SALES TOTAL
--------------- ------ ----- ----- -----
Colombian 101 7.99 0 0
French_Roast 49 8.99 0 0
Espresso 150 9.99 0 0
Colombian_Decaf 101 8.99 0 0
French_Roast_Decaf 49 9.99 0 0

  如果你直接在數據庫系統里輸入 SQL 查詢語句,你將在你的終端上看到如上的結果。當我們通過一個 Java 應用程序存取一個數據庫時,正如我們馬上要做的一樣,我們需要檢索結果以便我們能使用他們。你將在下一節看到如何實現。

這是 SELECT 語句的另一個例子,這將得到咖啡及其各自每磅單價的列表。

SELECT COF_NAME, PRICE FROM COFFEES

查詢的結果集將具有如下形式:

COF_NAME PRICE
-------- ---------- -----
Colombian 7.99
French_Roast 8.99
Espresso 9.99
Colombian_Decaf 8.99
French_Roast_Decaf 9.99

上面 SELECT 語句取得了所有咖啡的名字及價格。而下面的 SELECT 語句限制那些每磅價格低于 $9.00 的咖啡才被選擇。
SELECT COF_NAME, PRICE
FROM COFFEES
WHERE PRICE < 9.00

結果集將具有如下形式:

COF_NAME PRICE
-------- ------- -----
Colombian 7.99
French_Roast 8.99
Colombian Decaf 8.99



CNBIE BLOG

JDBC入門系列專題講座

原文:JDBC入門系列專題講座

  5. 安全性考慮

  作為網絡上的語言JAVA必須十分注安全性的考慮。基于上面的討論,JDBC的兩種主要使用場合里面,我們必須考慮安全性問題:

  * 在Java applications的場合里面Java代碼是本地的,所以也是"trusted"

  * 沒有驗證的Java applet代碼不可以存取本地的以及其他網絡的數據。

  5. 1. JDBC 和未驗證的applet

  JDBC首先必須符合JAVA的一般安全規則。另外:

  * JDBC 必須認為沒有驗證的applets是不可靠的。

  * JDBC 不可以讓不可靠的applets存取本地數據庫

  * 一個已經向JDBC DriverManager注冊的是JDBC Driver只能存取它所來的數據源。

  * 一個applet也只能向它所Download來的來存取數據。

  如果JDBC驅動層如果完全確信對一個數據庫打開連接不會引起認證或者權限問題(可能由網上隨機主機上運行的程序引起),那么它就允許applet打開這樣的連接。

  數據庫不通過IP地址來限制存取是相當少的,主要是為了舉例。(當心,這一段話我可能翻譯反了!!!大家看看原文。)這些限制是相當煩瑣的。不過他們與對一般applet的限制是一致的我們沒有必要放開這些限制。

  5. 2. JDBC 和Java應用程序

  對于一個普通的Java應用程序(例如全部用Java代碼而不是不可靠的applet )JDBC將從本地的類路徑里面獲得驅動,并且允許應用程序自由存取文件,遠程等等。

  但是和applet一樣,如果由于某些原因一個沒有驗證的sun.sql.Driver類從遠程的來源里面獲得,那么這個驅動只能和相同地方來的代碼配合。

  5. 3. Driver的安全責任

  JDBC driver可能在各種情況下使用,所以驅動的編制者遵循一定的簡單的安全規則,從而避免applet做非法的數據庫連接。

  如果所有的驅動都象applet一樣從網上下載,那么這些原則將是不必要的,因為普通的安全規則已經對它做了限制。

  但是驅動的編寫者必須記住一旦他們的驅動獲得成功,用戶將在本地磁盤安裝這些驅動,那么驅動將成為Java環境中一個被信任的部分,所以必須確信它不會被來訪的applet所濫用。所以我們鼓勵所有的驅動編寫者必須遵循一定安全原則。

  所有這些原則都是在連接打開的時候使用。這正式驅動和虛擬機器檢查當前調用者是否真的可以與指定的數據庫連接的時刻。一旦連接建立就不必做更多的檢查了。

  5. 3. 1. 分享TCP/IP連接的時候必須謹慎

  如果一個JDBC驅動試圖打開一個 TCP 連接,那么這個打開會被Java 安全管理機制自動檢查。這個機構會檢查當前調用棧里面有沒有applet,如果有那么就限定它可以訪問的機器集合。所以一般地JDBC驅動可以把TCP建立檢查留給Java虛擬機。

  但是如果一個JDBC驅動試圖在多個數據庫連接之間共享一個TCP連接,那么驅動就必須自己負責檢查每個調用者是否真的被允許與目標數據庫聯系。

  例如如果我們為applet A打開了一個通往機器foobah 的TCP連接,這并不意味著applet B被自動允許來共享這個連接。

  applet B可能沒有任何訪問機器foobah的權力。所以在允許某個程序重用一個現成的TCP連接之前,JDBC 驅動必須通過安全機構來檢查當前的的調用者是否可以訪問這個連接。通過下面的代碼可是實現這個功能。
  SecurityManager security = System.getSecurityManager();

  if (security != null)

  {

  security.checkConnect(hostName, portNumber);

  }

  如果連接是不允許的,那么Security.checkConnect方法將產生一個java.lang.SecurityException。

  5. 3. 2. 檢查所有的本地文件訪問

  如果一個JDBC取得需要訪問本地機器上的數據,那么他必須確信調用者是被允許打開這個文件的。例如:
  SecurityManager security = System.getSecurityManager();

  if (security != null)

  {

  security.checkRead(fileName);

  }

  如果對特定文件的訪問是不允許的,那么Security.checkRead方法將產生一個java.lang.SecurityException。

  5. 3. 3. 作好最壞的準備

  一些驅動可能使用本地的方法來橋接底層數據庫程序。則這些情況里面判斷那些本地文件將被底層函數所訪問是困難的。

  在這些環境里面用戶必須作好最壞的打算,并且否決所有下載applet所發出的數據庫存取,除非驅動可能完全確信將要做存取是沒有問題的。

  例如一個JDBC-ODBC橋接器必須檢查ODBC數據源的的名稱,確保applet只可以訪問它的"生源地"。如果對有的名字中不能判斷出數據源的主機名,那么只能否決這個訪問。

  為了決定一個當前的調用者是可以信賴的應用還是一個applet,JDBC驅動必須能夠檢查這個調用者是否可以寫一個隨機的文件:
  SecurityManager security = System.getSecurityManager();

  if (security != null)

  {

  security.checkWrite("foobaz");

  I. }

 

上一頁  [1] [2] [3] 



CNBIE BLOG

JDBC數據庫訪問例子(1)

原文:JDBC數據庫訪問例子(1)
JDBC數據庫訪問例子

  JAVA語言的跨平臺的工作能力(Write Once ,Run Anywhere)、優秀的圖像處理能力(我相信現在沒有那種語言可以超過JAVA在網絡上的圖形處理能力)、網絡通信功能、通過JDBC數據庫訪問技術等等,讓我們誰都不可否認JAVA語言是SUN公司對于計算機界的一個巨大的貢獻。筆者可以描述這樣一個場景:有一天你上網完全可以不用IE 或者NETSCAPE,上網就像是玩游戲,你可以獲得游戲那么精美的圖像和互動的感覺,如果你玩過UO,也許你就知道那種感覺了,但是JAVA做成的東西一定會超過UO的,因為不單單是游戲,也不是單單是瀏覽器,如果你愿意(要你有錢,有時間,有優秀的JAVA人才)你可以把所有的這一切用Java完全集成出來!!!我不是夸大JAVA的功能,大家可以訪問一下http://www.simchina.net的那個社區程序,你就能找到一種感覺了:相信我沒有說什么假話 。好了,不說廢話了,現在我向你介紹JAVA的數據庫訪問技術----JDBC數據庫訪問技術(你可千萬不要搞成ODBC了喲!)。

  JDBC技術事實上是一種能通過JAVA語言訪問任何結構化數據庫的應用程序接口(API)(Sun這樣說的,我也不知道是不是真的),而且現在的JDBC 3.0據Sun說也能訪問Execel等電子表格程序!

  JDBC對于數據庫的訪問有四種方式,我們這里只是介紹兩種:

  第一種是通過ODBC做為“橋”(Bridge)對數據庫訪問,第二種是直接對數據庫訪問。

  我們先來看看第一種JDBC<-->ODBC訪問的流程:

  JDBC Driver Mannager->JDBC<->ODBC橋->ODBC->數據庫客戶機驅動庫->數據庫服務器->返回查詢結果,在這種訪問中值的我們注意的是雖然JAVA是"Write Once ,Run Anywhere",但是如果通過這種訪問的話,需要客戶端必須設置ODBC和有相應的數據庫客戶機的驅動,當你看了下面的另外一個流程的時候或許你會想:明明下一種更方面,為什么還要有這個東西的產生!呵呵,因為,未必所有的數據庫服務器提供商都提供下面的JDBC驅動程序(給JDBC訪問提供相應的接口),所以就有了JDBC<->ODBC Bridge。

  接著再讓我們來看看第二種訪問流程:

  JDBC Driver Mannager->局部JDBC驅動->客戶端數據庫->數據庫服務器->返回查詢結果,這種訪問事實上是轉換JDBC調用為相應的數據庫(Oracle, Sybase, Informix, DB2, 和其他的數據庫數據庫管理系統)的客戶端API調用(這么說,不知道大家能不能懂,說簡單點就好像ASP不是通過DSN對數據庫訪問而是通過OLEDB訪問,說道這里我還是不知道大家能不能明白我的意思。哎呀,不要扔雞蛋嘛!),這種方式的訪問需要相應的數據庫提供商提供相應的JDBC驅動程序,但是有一種好處,可以獨立于odbc用于可以隨處可Run的客戶端的瀏覽器中的Applet程序。
我們下面將給大家一個通過JDBC-ODBC橋數據庫訪問的實例,但是在看下面的事例前我想問大家一次:JDK1.3裝了嗎?數據庫驅動裝了嗎(我使用的是SQLserver)?你該沒有使用Linux吧?雖然java支持Linux,但是老兄我可沒有使用Linux喲(這同JAVA的Write Once ,Run Anywhere沒有關系),由于使用了運行于Win下面的ODBC,我建議你看看這篇東西http://www.aspcn.com/showarticle.asp?id=112,否則你要是有了問題,出不了結果那豈不是要怪我(不過欲加之罪,何患無吃... ...),冤枉呀!




CNBIE BLOG

JDBC系列教程(一)---連接

原文:JDBC系列教程(一)---連接
連接
本概述是從《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》這本書中摘引來的。JavaSoft 目前正在準備這本書。這本書是一本教程,同時也是 JDBC 的重要參考手冊,它將作為 Java 系列的組成部份在 1997 年春季由 Addison-Wesley 出版公司出版。


2.1 概述
Connection 對象代表與數據庫的連接。連接過程包括所執行的 SQL 語句和在該連接上所返回的結果。一個應用程序可與單個數據庫有一個或多個連接,或者可與許多數據庫有連接。


2.1.1 打開連接
數據庫建立連接的標準方法是調用 DriverManager.getConnection 方法。該方法接受含有某個 URL 的字符串。DriverManager 類(即所謂的 JDBC 管理層)將嘗試找到可與那個 URL 所代表的數據庫進行連接的驅動程序。DriverManager 類存有已注冊的 Driver 類的清單。當調用方法 getConnection 時,它將檢查清單中的每個驅動程序,直到找到可與 URL 中指定的數據庫進行連接的驅動程序為止。Driver 的方法 connect 使用這個 URL 來建立實際的連接。

用戶可繞過 JDBC 管理層直接調用 Driver 方法。這在以下特殊情況下將很有用:當兩個驅動器可同時連接到數據庫中,而用戶需要明確地選用其中特定的驅動器。但一般情況下,讓 DriverManager 類處理打開連接這種事將更為簡單。

下述代碼顯示如何打開一個與位于 URL "jdbc:odbc:wombat" 的數據庫的連接。所用的用戶標識符為 "oboy" ,口令為 "12Java":

String url = "jdbc:odbc:wombat";
Connection con = DriverManager.getConnection(url, "oboy", "12Java");

2.1.2 一般用法的 URL
由于 URL 常引起混淆,我們將先對一般 URL 作簡單說明,然后再討論 JDBC URL。

URL(統一資源定位符)提供在 Internet 上定位資源所需的信息。可將它想象為一個地址。

URL 的第一部份指定了訪問信息所用的協議,后面總是跟著冒號。常用的協議有 "ftp"(代表“文件傳輸協議”)和 "http" (代表“超文本傳輸協議”)。如果協議是 "file",表示資源是在某個本地文件系統上而非在 Internet 上(下例用于表示我們所描述的部分;它并非 URL 的組成部分)。

ftp://javasoft.com/docs/JDK-1_apidocs.zip
http://java.sun.com/products/jdk/CurrentRelease
file:/home/haroldw/docs/books/tutorial/summary.html

URL 的其余部份(冒號后面的)給出了數據資源所處位置的有關信息。如果協議是 file,則 URL 的其余部份是文件的路徑。對于 ftp 和 http 協議,URL 的其余部份標識了主機并可選地給出某個更詳盡的地址路徑。例如,以下是 JavaSoft 主頁的 URL。該 URL 只標識了主機:

http://java.sun.com

從該主頁開始瀏覽,就可以進到許多其它的網頁中,其中之一就是 JDBC 主頁。JDBC 主頁的 URL 更為具體,它看起來類似:

http://java.sun.com/products/jdbc

2.1.3 JDBC URL
JDBC URL 提供了一種標識數據庫的方法,可以使相應的驅動程序能識別該數據庫并與之建立連接。實際上,驅動程序編程員將決定用什么 JDBC URL 來標識特定的驅動程序。用戶不必關心如何來形成 JDBC URL;他們只須使用與所用的驅動程序一起提供的 URL 即可。JDBC 的作用是提供某些約定,驅動程序編程員在構造他們的 JDBC URL 時應該遵循這些約定。

由于 JDBC URL 要與各種不同的驅動程序一起使用,因此這些約定應非常靈活。首先,它們應允許不同的驅動程序使用不同的方案來命名數據庫。例如, odbc 子協議允許(但并不是要求) URL 含有屬性值。

第二,JDBC URL 應允許驅動程序編程員將一切所需的信息編入其中。這樣就可以讓要與給定數據庫對話的 applet 打開數據庫連接,而無須要求用戶去做任何系統管理工作。

第三, JDBC URL 應允許某種程度的間接性。也就是說,JDBC URL 可指向邏輯主機或數據庫名,而這種邏輯主機或數據庫名將由網絡命名系統動態地轉換為實際的名稱。這可以使系統管理員不必將特定主機聲明為 JDBC 名稱的一部份。網絡命名服務(例如 DNS、 NIS 和 DCE )有多種,而對于使用哪種命名服務并無限制。

JDBC URL 的標準語法如下所示。它由三部分組成,各部分間用冒號分隔:

jdbc::

JDBC URL 的三個部分可分解如下:


jdbc ─ 協議。JDBC URL 中的協議總是 jdbc。


─ 驅動程序名或數據庫連接機制(這種機制可由一個或多個驅動程序支持)的名稱。子協議名的典型示例是 "odbc",該名稱是為用于指定 ODBC 風格的數據資源名稱的 URL 專門保留的。例如,為了通過 JDBC-ODBC 橋來訪問某個數據庫,可以用如下所示的 URL:
jdbc:odbc:fred

本例中,子協議為 "odbc",子名稱 "fred" 是本地
ODBC 數據資源。

如果要用網絡命名服務(這樣 JDBC URL 中的數據庫名稱不必是實際名稱),則命名服務可以作為子協議。例如,可用如下所示的 URL :

jdbc:dcenaming:accounts-payable

本例中,該 URL 指定了本地 DCE 命名服務應該將
數據庫名稱 "accounts-payable" 解析為更為具體的
可用于連接真實數據庫的名稱。


─ 一種標識數據庫的方法。子名稱可以依不同的子協議而變化。它還可以有子名稱的子名稱(含有驅動程序編程員所選的任何內部語法)。使用子名稱的目的是為定位數據庫提供足夠的信息。前例中,因為 ODBC 將提供其余部份的信息,因此用 "fred" 就已足夠。然而,位于遠程服務器上的數據庫需要更多的信息。例如,如果數據庫是通過 Internet 來訪問的,則在 JDBC URL 中應將網絡地址作為子名稱的一部份包括進去,且必須遵循如下所示的標準 URL 命名約定:
//主機名:端口/子協議

假設 "dbnet" 是個用于將某個主機連接到 Internet 上的協議,則 JDBC URL 類似:

jdbc:dbnet://wombat:356/fred

2.1.4 "odbc" 子協議
子協議 odbc 是一種特殊情況。它是為用于指定 ODBC 風格的數據資源名稱的 URL 而保留的,并具有下列特性:允許在子名稱(數據資源名稱)后面指定任意多個屬性值。odbc 子協議的完整語法為:


jdbc:odbc:[;=]*

因此,以下都是合法的 jdbc:odbc 名稱:

jdbc:odbc:qeor7
jdbc:odbc:wombat
jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER
jdbc:odbc:qeora;UID=kgh;PWD=fooey

2.1.5 注冊子協議
驅動程序編程員可保留某個名稱以將之用作 JDBC URL 的子協議名。當 DriverManager 類將此名稱加到已注冊的驅動程序清單中時,為之保留該名稱的驅動程序應能識別該名稱并與它所標識的數據庫建立連接。例如,odbc 是為 JDBC- ODBC 橋而保留的。示例之二,假設有個 Miracle 公司,它可能會將 "miracle" 注冊為連接到其 Miracle DBMS 上的 JDBC 驅動程序的子協議,從而使其他人都無法使用這個名稱。

JavaSoft 目前作為非正式代理負責注冊 JDBC 子協議名稱。要注冊某個子協議名稱,請發送電子郵件到下述地址:

jdbc@wombat.eng.sun.com

2.1.6 發送 SQL 語句
連接一旦建立,就可用來向它所涉及的數據庫傳送 SQL 語句。JDBC 對可被發送的 SQL 語句類型不加任何限制。這就提供了很大的靈活性,即允許使用特定的數據庫語句或甚至于非 SQL 語句。然而,它要求用戶自己負責確保所涉及的數據庫可以處理所發送的 SQL 語句,否則將自食其果。例如,如果某個應用程序試圖向不支持儲存程序的 DBMS 發送儲存程序調用,就會失敗并將拋出異常。JDBC 要求驅動程序應至少能提供 ANSI SQL-2 Entry Level 功能才可算是符合 JDBC 標準TM 的。這意味著用戶至少可信賴這一標準級別的功能。

JDBC 提供了三個類,用于向數據庫發送 SQL 語句。Connection 接口中的三個方法可用于創建這些類的實例。下面列出這些類及其創建方法:


Statement ─ 由方法 createStatement 所創建。Statement 對象用于發送簡單的 SQL 語句。
PreparedStatement ─ 由方法 prepareStatement 所創建。PreparedStatement 對象用于發送帶有一個或多個輸入參數( IN 參數)的 SQL 語句。PreparedStatement 擁有一組方法,用于設置 IN 參數的值。執行語句時,這些 IN 參數將被送到數據庫中。PreparedStatement 的實例擴展了 Statement ,因此它們都包括了 Statement 的方法。PreparedStatement 對象有可能比 Statement 對象的效率更高,因為它已被預編譯過并存放在那以供將來使用。
CallableStatement ─ 由方法 prepareCall 所創建。CallableStatement 對象用于執行 SQL 儲存程序 ─ 一組可通過名稱來調用(就象函數的調用那樣)的 SQL 語句。CallableStatement 對象從 PreparedStatement 中繼承了用于處理 IN 參數的方法,而且還增加了用于處理 OUT 參數和 INOUT 參數的方法。

以下所列提供的方法可以快速決定應用哪個 Connection 方法來創建不同類型的 SQL 語句:


createStatement 方法用于:


簡單的 SQL 語句(不帶參數)


prepareStatement 方法用于:


帶一個或多個 IN 參數的 SQL 語句


經常被執行的簡單 SQL 語句


prepareCall 方法用于:


調用已儲存過程


2.1.7 事務
事務由一個或多個這樣的語句組成:這些語句已被執行、完成并被提交或還原。當調用方法 commit 或 rollback 時,當前事務即告就結束,另一個事務隨即開始。

缺省情況下,新連接將處于自動提交模式。也就是說,當執行完語句后,將自動對那個語句調用 commit 方法。這種情況下,由于每個語句都是被單獨提交的,因此一個事務只由一個語句組成。如果禁用自動提交模式,事務將要等到 commit 或 rollback 方法被顯式調用時才結束,因此它將包括上一次調用 commit 或 rollback 方法以來所有執行過的語句。對于第二種情況,事務中的所有語句將作為組來提交或還原。

方法 commit 使 SQL 語句對數據庫所做的任何更改成為永久性的,它還將釋放事務持有的全部鎖。而方法 rollback 將棄去那些更改。

有時用戶在另一個更改生效前不想讓此更改生效。這可通過禁用自動提交并將兩個更新組合在一個事務中來達到。如果兩個更新都是成功的,則調用 commit 方法,從而使兩個更新結果成為永久性的;如果其中之一或兩個更新都失敗了,則調用 rollback 方法,以將值恢復為進行更新之前的值。

大多數 JDBC 驅動程序都支持事務。事實上,符合 JDBC 的驅動程序必須支持事務。DatabaseMetaData 給出的信息描述 DBMS 所提供的事務支持水平。


2.1.8 事務隔離級別
如果 DBMS 支持事務處理,它必須有某種途徑來管理兩個事務同時對一個數據庫進行操作時可能發生的沖突。用戶可指定事務隔離級別,以指明 DBMS 應該花多大精力來解決潛在沖突。例如,當事務更改了某個值而第二個事務卻在該更改被提交或還原前讀取該值時該怎么辦? 假設第一個事務被還原后,第二個事務所讀取的更改值將是無效的,那么是否可允許這種沖突? JDBC 用戶可用以下代碼來指示 DBMS 允許在值被提交前讀取該值(“dirty 讀取”),其中 con 是當前連接:

con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

事務隔離級別越高,為避免沖突所花的精力也就越多。Connection 接口定義了五級,其中最低級別指定了根本就不支持事務,而最高級別則指定當事務在對某個數據庫進行操作時,任何其它事務不得對那個事務正在讀取的數據進行任何更改。通常,隔離級別越高,應用程序執行的速度也就越慢(由于用于鎖定的資源耗費增加了,而用戶間的并發操作減少了)。在決定采用什么隔離級別時,開發人員必須在性能需求和數據一致性需求之間進行權衡。當然,實際所能支持的級別取決于所涉及的 DBMS 的功能。

當創建 Connection 對象時,其事務隔離級別取決于驅動程序,但通常是所涉及的數據庫的缺省值。用戶可通過調用 setIsolationLevel 方法來更改事務隔離級別。新的級別將在該連接過程的剩余時間內生效。要想只改變一個事務的事務隔離級別,必須在該事務開始前進行設置,并在該事務結束后進行復位。我們不提倡在事務的中途對事務隔離級別進行更改,因為這將立即觸發 commit 方法的調用,使在此之前所作的任何更改變成永久性的。


CNBIE BLOG

JDBC學習筆記(保持更新)

原文:JDBC學習筆記(保持更新)

一、幾種裝載JDBC驅動程序的方法


1.    在DriverManager中注冊
舉例:在DriverManager中注冊Oracle JDBC Driver
    // 注冊Oracle JDBC 驅動器
    DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
2.    直接裝載

二、常見問題


在WebLogic 6.x中連接Oracle 9i數據庫時,可能會出現類似如下錯誤:
java.sql.SQLException: ORA-00600: 內部錯誤代碼,參數: [ttcgcshnd-1], [0], [], [], [], [], [],[]

示例代碼:
  1.     // 注冊Oracle JDBC 驅動器
  2.     DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
  3.  
  4.     // 注意連接url的格式:jdbc:oracle:thin:@ip:port:sid
  5.     java/lang/String.java.html" target="_blank">String url = "jdbc:oracle:thin:@192.168.0.1:1521:mydb";
  6.     java/lang/String.java.html" target="_blank">String userName = "scott";
  7.     java/lang/String.java.html" target="_blank">String password = "tiger";
  8.  
  9.     Connection conn =
  10.       DriverManager.getConnection (url, userName, password);
  11.  
  12.     // Create a Statement
  13.     Statement stmt = conn.createStatement();
  14.  
  15.     // 從EMP表中查詢員工姓名
  16.     ResultSet rs = stmt.executeQuery ("select ENAME from EMP");
  17.  
  18.     // 在結果集中取出第一列,即ENAME
  19.     while (rs.next ()) {
  20.       java/lang/System.java.html" target="_blank">System.out.println (rs.getString (1));
  21.     }


原因分析:在WebLogic的核心包weblogic.jar($WEBLOGIC\lib)中內置了Oracle8i的驅動器,這個錯誤就是由于使用了Oracle8i的驅動器訪問Oracle9i造成的。

解決辦法:將Oracle9i的JDBC Driver(如果你安裝了Oracle9i的服務器或客戶端,在$ORACLE\ora90\jdbc\lib下就包含了classes12.zip或者classes12.jar)加入到你的WebLogic當前域的啟動腳本(startWebLogic.cmd)中。特別注意,這個.jar一定要位于weblogic.jar之前!

版聲說明:本文僅授權JavaResearch.org發表,嚴禁其它網站、媒體轉載。




CNBIE BLOG

JDBC學習筆記-----jdbc性能優化[轉載]

原文:JDBC學習筆記-----jdbc性能優化[轉載]

jdbc程序的性能主要由兩個因素決定,一是數據庫本身的性質,另一個是與數據庫相對獨立的jdbc應用程序接口(api)的使用.這里說的是如何正確使用jdbc編程接口,以獲得更好的性能.
  jdbc主要優化有:
     1.選擇正確的jdbc驅動程序
     2.Connention的優化  使用連接池來管理Connection對象
     3.Statement的優化   使用批量更新等
     4.Result的優化  正確的從數據庫中get數據等
     
     (1)選擇正確的jdbc驅動程序:
  1 jdbc-odbc 橋
            2 本地api-部分 java驅動
                3 jdbc網路協議-純java驅動
                4 jdbc本地協議
                最好選擇 jdbc網路協議-純java驅動  效率比較高  但需要第三方軟件的支持 比如corba  weblogic屬于這種類型
    
     (2)優化Connection對象:
         1.設置適當的參數  DriverManager.getConnection(String url,Properties props);
                 例如:     Properties props=new Properties();
      props.put("user","wuwei");
      props.put("password","wuwei");
            props.put("defaultRowPrefectch","30");
                           props.put("dufaultBatchValue","5");
                           Connection con=DriverManager.getConnection("jdbcracle:thin:@hostsString",props);
             對象可以通過設置setDefaultRowPrefetch(int) 和 setDefaultBatchValue(int) 兩個參數類優化連接

 2.使用連接池  可以自己寫一個連接池 這樣程序的靈活性強,便于移植.
      apache項目開發了一套非常通用而表現非常穩定的對象池 http://jakarta.apache.org/commons/pool.htm
      設計了自己的連接池后 在客戶端調用建立對象
                           public Object makeObject() throws Exception{
    Class.forName("oracle.jdbc.driver.OracalDriver");
    return DriverManager.getConnection("url","username","password");
      }
                  銷毀對象時用
      public void destroyObject(Object obj) throws Exception{
         ((Connection)obj.close());
      }
        注意幾點 對象池里有沒有回收機制,對象池里有機有容量限制,對象池里有多少個閑置對象(可以釋放)        
  
        3.控制事務的提交  最好手動提交事務,不但可以可以保證數據原子性,而且對新能提高留下余地.
                   try{
   connection.setAutoCommint(false);
                        // 代碼 用PreparedStatement  性能比Statementh好.

                        connection.commit();
                        connection.setAutoCommit(true);
     }
            catch(SQLException e){
                   }
                   finally{
   //代碼
   if(connection!=null){
      connection.close();  
   }
       }

 4.適當的選擇事務的隔離級別   TRANSACTION_READ_UNCOMMITED  性能最高
                                     TRANSACTION_READ_COMMITED    快
                                     TRANSACTION_REFEATABLE_READ  中等
            RANSACTION_SERIALIZABLE      慢
 
   (3)Statement 優化
      jdbc3個接口用來處理sql的執行,是Statement PreparedStatement CallableStatement
          提供適當的Statement接口 
          批量執行sql
          從數據庫批量獲取數據
      PreparedStatement 比Statement性能要好 主要體現在一個sql語句多次重復執行的情況
      PreparedStatemnt只編譯解析一次而Statement每次編譯一次.
      
      批量修改數據庫   
 Statement 提供了方法addBatch(String)和executeBatch()
        調用方法為stmt.addBatch("isnert....."); stmt.addBatch("update.....")
                  stmt.executeBatch();
        也可以用PreparedStatement從而更好的提高性能.
                pstmt=conn.preparedStatement("insert into test_table(......) values(....?)");
                pstmt.setString(1,"aaa");
                pstmt.addBatch();
                pstmt.setString(1,"bbb");
                pstmt.addBatch();
                .....
                pstmt.executeBatch();
 
      批量地從數據庫中取數據.
          通過setFetchSize()和getFectchSize()方法來設定和查看這個參數.這個參數對體統的性能影響比較大.
          這個參數太小會嚴重地降低程序地性能.
   Connection Statement ResultSet都有這個參數,他們對性能地影響順序是:
             ResultSet---------Statement---------Connection
  (4)優化ResultSet.
     體現在以下幾個方面
        批量讀取數據.合理設置ResultSet的getFetchSize()和setFetchSize()方法中的參數
        使用正確的get和set方法
             使用整數而不是字段名作為參數性能比較高,
             例如 setInt(1,100);
                  setString(2,"aaaa");
               比 setInt("id","100");
                  setString("name","aaaa");
               性能好
        設置適當的滾動方向.有3個方向FETCH_FORWORD,FETCH_REVERSE FETCH_UNKNOWN
             單向滾動性能比較高.
  其他方面的性能優化
      及時顯示的關閉Connection Statement ResultSet
          其中Connection可以用Connetion Pool處理.
      使用數據庫系統的強大查詢功能去組織數據.這樣程序運行是和數據庫服務的交互次數少,數據庫返回給
      程序的記錄條數少的多,所以性能有很大的提高.


作者不清

 jinijxta 回復于:2003-08-29 11:56:04
在服務器端能用SQLJ處理的商務邏輯最好不要放在客戶端,否則客戶端代碼維護十分不便

 selen 回復于:2003-08-29 20:47:25
我有個應用是WEBLOGCI于PROGRESS連接的但是發現JDBC的接口效率不如原來用JDBC-ODBC的高,而且經常會斷開。請大家幫助分析一
下。