數據庫連接可以說是學習web最基礎的部分,也是非常重要的一部分,今天我們就來介紹下數據庫的連接為下面學習真正的web打下基礎
java中連接數據庫一般有兩種方式:
1.ODBC——Open Database Connectivity(開放數據庫連接性):基於C語言的一套數據庫編程接口,主要功能是提供數據庫的訪問和操作
所有的數據庫廠商對這套接口進行實現,不同數據庫廠商提供的實現是不一樣的,也就是通常所說的第三方支持,而這套編程接口就是我們的標准
2.JDBC——Java Database Connectivity(java版的ODBC)
專門為java語言提供的一套訪問操作數據庫的編程標准,由sun公司提供,所有可以被java語言操作的數據庫廠商都對其進行了實現
我們一般都是采用JDBC,優勢:
1.效率上jdbc會相對的高一些
2.安全角度來考慮,jdbc比odbc高
3.jdbc使用非常方便,只要加入相應的驅動包就可以了,而不像odbc還需要Jdbc-odbc橋驅動
4.使用jdbc可以很方便在各類數據庫間進行更換,只要更改相應的驅動就可以了
下面列舉用jdbc連接各類數據庫的方式:
常用JDBC連接數據庫方法總結如下: 一、JDBC連接DB2 Class.forName("Com.ibm.db2.jdbc.net.DB2Driver"); String url="jdbc:db2://dburl:port/DBname" cn = DriverManager.getConnection( url, sUsr, sPwd ); 二、JDBC連接Microsoft SQLServer(microsoft) Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" ); cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://DBServerIP:1433;databaseName=master", sUsr, sPwd ); 三、JDBC連接Sybase(jconn2.jar) Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" ); cn = DriverManager.getConnection( "jdbc:sybase:Tds:DBServerIP:2638", sUsr, sPwd ); 四、JDBC連接MySQL(mm.mysql-3.0.2-bin.jar) Class.forName( "org.gjt.mm.mysql.Driver" ); cn = DriverManager.getConnection( "jdbc:mysql://DBServerIP:3306/myDatabaseName", sUsr, sPwd ); 五、JDBC連接PostgreSQL(pgjdbc2.jar) Class.forName( "org.postgresql.Driver" ); cn = DriverManager.getConnection( "jdbc:postgresql://DBServerIP/myDatabaseName", sUsr, sPwd ); 六、JDBC連接Oracle(classes12.jar) Class.forName( "oracle.jdbc.driver.OracleDriver" ); cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd ); 七、JDBC連接ODBC Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ); Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );
下面我以Microsoft SQLServer 2000為例進行數據庫連接的講解,我們在連接前先將jar包放到項目的lib目錄下,這里我們只需jtds-1.2.5.jar
下面我們先來看一段完整連接數據庫代碼:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class JdbcTest { //數據庫的連接驅動,一般是不需要變的 private static final String DRIVER="com.microsoft.jdbc.sqlserver.SQLServerDriver"; //數據庫連接的URL,1433為默認的數據庫端口號,test為當前你要操作的數據庫名 private static final String URL="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test"; //登錄賬戶 private static final String DBNAME="sa"; //登錄的密碼 private static final String DBPASS="123"; public void test(){ Connection con=null; PreparedStatement psm=null; ResultSet rs=null; try{ Class.forName(DRIVER); con = DriverManager.getConnection(URL,DBNAME,DBPASS); String sql="select* from admin where id=1"; psm=con.prepareStatement(sql); rs=psm.executeQuery(); while(rs.next()){ System.out.println(rs.getString("aPassword")); } }catch(Exception e){ con.close(); rs.close(); psm.close(); e.printStackTrace(); }finally{ if(rs!=null){ rs.close(); } if(psm==null){ psm.close(); } if(con!=null){ con.close(); } } } }
對於上面的數據庫連接查詢,我們分6步來進行分析:
a.加載JDBC驅動程序:
在連接數據庫之前,首先要加載想要連接的數據庫的驅動到JVM(Java虛擬機),這通過java.lang.Class類的靜態方法forName(String className)實現。
如上面代碼:Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); 我們在單獨進行連接時一般要在進行異常的捕獲,即加上try..catch
try{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
}catch(ClassNotFoundException e){
System.out.println("找不到驅動程序類 ,加載驅動失敗!");
e.printStackTrace() ;
}
成功加載后,會將Driver類的實例注冊到DriverManager類中。
b.提供JDBC連接的URL並進行連接 :
如上面的代碼:(也進行異常的捕獲)
private static final String URL="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test";
private static final String DBNAME="sa";
private static final String DBPASS="123";
try{
con = DriverManager.getConnection(URL,DBNAME,DBPASS);
}catch{
System.out.println("數據庫連接失敗");
e.printStackTrace() ;
}
c.創建一個Statement
•要執行SQL語句,必須獲得java.sql.Statement實例,Statement實例分為以下3種類型:
1.執行靜態SQL語句。通常通過Statement實例實現。
2.執行動態SQL語句。通常通過PreparedStatement實例實現。
3.執行數據庫存儲過程。通常通過CallableStatement實例實現。
具體的實現方式:
1.Statement stmt = con.createStatement() ;
2.如上代碼:PreparedStatement psm = con.prepareStatement(sql) ;
3.CallableStatement cstmt = con.prepareCall("{CALL demoSp(? , ?)}") ;
d.執行SQL語句
Statement接口提供了三種執行SQL語句的方法:executeQuery 、executeUpdate 和execute
1.ResultSet executeQuery(String sqlString):執行查詢數據庫的SQL語句 ,返回一個結果集(ResultSet)對象。
2.int executeUpdate(String sqlString):用於執行INSERT、UPDATE或DELETE語句以及SQL DDL語句,如:CREATE TABLE和DROP TABLE等
3.execute(sqlString):用於執行返回多個結果集、多個更新計數或二者組合的語句。
具體實現的代碼:
ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ;
int rows = stmt.executeUpdate("INSERT INTO ...") ;
boolean flag = stmt.execute(String sql) ;
e.處理結果
兩種情況:
1.執行更新返回的是本次操作影響到的記錄數。
2.執行查詢返回的結果是一個ResultSet對象。
• ResultSet包含符合SQL語句中條件的所有行,並且它通過一套get方法提供了對這些行中數據的訪問。
• 使用結果集(ResultSet)對象的訪問方法獲取數據:
如上例:
while(rs.next()){
System.out.println(rs.getString("aPassword"));
}
處理結果集還有種方式就是:根據數據庫表列的編號(從左到右,第一列為1)如rs.getString(1)表示獲取對應表中第一列的數據
f.關閉JDBC對象
操作完成以后要把所有使用的JDBC對象全都關閉,以釋放JDBC資源,關閉順序和聲明順序相反:
1.關閉記錄集
if(rs!=null){
rs.close();
}
2.關閉聲明
if(psm==null){
psm.close();
}
3.關閉連接對象
if(con!=null){
con.close();
}
連接數據庫基本結束,里面包含的有些基礎方面的知識大家自己回去看看書吧,我這里還提供一個封裝好了的數據庫連接操作,只需要調用即可
http://www.cnblogs.com/shenliang123/archive/2012/04/19/2456665.html
下次我們將進行數據庫操作的實戰
注:
java中PreparedStatement和Statement區別
第一:
數據庫在執行sql語句的時候如果使用PreparedStatement語句會有一點優勢:因為數據庫會preparedStatement
語句進行預編譯,下次執行相同的sql語句時,數據庫端不會再進行預編譯了,而直接用數據庫的緩沖區,提高數據訪問的效率(但盡量盡量采用使用?號的方式傳遞參數),如果sql語句只執行一次,以后不再復用.
第二:
在JDBC應用中,如果你已經是稍有水平開發者,你就應該始終以PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement. 基於以下的原因:
一.代碼的可讀性和可維護性.
雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護性上來說.都比直接用Statement的代碼高很多檔次:
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)"); perstmt.setString(1,var1); perstmt.setString(2,var2); perstmt.setString(3,var3); perstmt.setString(4,var4); perstmt.executeUpdate();
不用我多說,對於第一種方法.別說其他人去讀你的代碼,就是你自己過一段時間再去讀,都會覺得傷心.
二.PreparedStatement盡最大可能提高性能.
每一種數據庫都會盡最大努力對預編譯語句提供最大的性能優化.因為預編譯語句有可能被重復調用.所以語句在被DB的編譯器編譯后的執行代碼被緩存下來,那么下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中(相當於一個涵數)就會得到執行.這並不是說只有一個Connection中多次執行的預編譯語句被緩存,而是對於整個DB中,只要預編譯的語句語法和緩存中匹配.那么在任何時候就可以不需要再次編譯而可以直接執行.而statement的語句中,即使是相同一操作,而由於每次操作的數據不同所以使整個語句相匹配的機會極小,幾乎不太可能匹配.比如: insert into tb_name (col1,col2) values ('11','22'); insert into tb_name (col1,col2) values ('11','23');
即使是相同操作但因為數據內容不一樣,所以整個個語句本身不能匹配,沒有緩存語句的意義.事實是沒有數據庫會對普通語句編譯后的執行代碼緩存.
當然並不是所以預編譯語句都一定會被緩存,數據庫本身會用一種策略,比如使用頻度等因素來決定什么時候不再緩存已有的預編譯結果.以保存有更多的空間存儲新的預編譯語句.
三.最重要的一點是極大地提高了安全性. (sql注入)
String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我們把[' or '1' = '1]作為varpasswd傳入進來.用戶名隨意,看看會成為什么?
select * from tb_name = '隨意' and passwd = '' or '1' = '1'; 因為'1'='1'肯定成立,所以可以任何通過驗證.更有甚者: 把[';drop table tb_name;]作為varpasswd傳入進來,則:
select * from tb_name = '隨意' and passwd = '';drop table tb_name;有些數據庫是不會讓你成功的,但也有很多數據庫就可以使這些語句得到執行.
而如果你使用預編譯語句.你傳入的任何內容就不會和原來的語句發生任何匹配的關系.只要全使用預編譯語句,你就用不着對傳入的數據做任何過慮.而如果使用普通的statement,有可能要對drop,;等做費盡心機的判斷和過慮.
