JDBC(Java Database Connectivity)提供了訪問數據庫的API,由一些Java類和接口組成,是Java運行平台核心庫中的一部分。用Java語言編寫的數據庫驅動程序稱為JDBC數據驅動程序。
也就是說使用JDBC可以達到通過JDBC實現應用程序操縱數據庫的效果。
使用JDBC進行如下操作:
JDBC可以調用本地的JDBC數據庫驅動程序和相應的數據庫建立連接,一般有如下步驟:
(1)加載JDBC數據庫驅動程序
不同數據庫廠商提供了不同的JDBC驅動程序,想要連接操作數據庫時,就必須下載相應的JDBC。比如MySQL的JDBC可以去mysql的官網下載,將下載到的JDBC數據庫驅動程序(mysql-connector-java*.jar)復制到Tomcat所使用的JDK的拓展目錄中(../jre/lib/ext),或者復制到tomcat的安裝目錄/common/lib下。
//應用程序加載MySQL的JDBC數據庫驅動程序代碼 try{ Class.forName("com.mysql.jdbc.Driver"); }catch(Exception e){}(2)與指定的數據庫建立連接
Java.sql包中的DriverManager類中有兩個用於建立連接的類方法(static方法):
Connection getConnection(java.lang.String,java.lang.String,java.lang.String) Connection getConnection(java.lang.String)
它們都會拋出SQLException異常。DriverManger類調用上面的方法可以和數據庫建立連接,返回一個connection對象。
假設mysql服務正常啟動,其服務器ip為192.3.4.5,使用默認端口3306,用戶pinnsvin的密碼是pinnsvin,並且對數據庫test有所有權限,那麼建立連接代碼如下:
//使用三個參數的方法 try{ String uri="jdbc:mysql;//192.3.4.5:3306/test"; String user="pinnsvin"; String password="pinnsvin"; con=DriverManager.getConnection(uri,user,pass); } catch(SQLException e){ System.out.println(e); } //使用一個參數的方法 try{ String uri="jdbc:mysql://192.3.4.5:3306/test?user=pinnsvin&password=pinnsvin"; con=DriverManger.getConnection(uri); } catch(SQLException e){ System.out.println(e); }
(1)數據庫和表使用中文支持的字符編碼
關於在DBMS中設置編碼方式可以參考MySQL設置字符編碼一文.
(2)連接數據庫支持中文編碼
try{ Class.forName("com.mysql.jdbc.Driver"); }catch(Exception e){ System.out.print(“忘記把mysql數據庫的JDBC驅動程序復制到JDK的拓展目錄或tomcat*/common/lib中了"); } try{ String uri="jdbc:mysql://127.0.0.1/test?user=pinnsvin&password=pinnsvin&characterEncoding=utf8"; con=DriverManager.getConnection(uri); } catch(SQLException e){ System.out.print(e); }
和數據庫建立連接後,就可以使用JDBC提供的API與數據庫交互信息,比如查詢、插入、更新、刪除數據庫表中數據以及對標的操縱。
數據庫的查詢結果會返回到一個Resquest對象中,習慣上稱Request對象為結果集對象。
(1)SQL語句對象
使用Statement聲明一個SQL語句對象,然後讓已創建連接的對象con調用方法createStatement() 創建這個SQL語句對象,代碼:
try{ Statement sql=con.createStatement(); } catch(SQLException e){ System.out.print(e); }(2)SQL語句對象調用方法查詢數據
SQL語句對象可以調用相應的方法查詢數據庫中的表,並將查詢結果放在一個Resquest結果集中。例如:
Resquest rs=sql.executeQuery(“SELECT name,sex FROM user”);
結果集對象rs有兩列,第一列是name,第二列是sex。
Request結果集一次只能看一個數據行,使用next()方法走到下一行。
Request類常用方法
ResultSetMetaData md=rs.getMetaData(); int colcount=md.getColumnCount();
ResultSetMetaData md=rs.getMetaData(); String colname=md.getColumnName(i);
有時候我們需要一個可滾動的結果集,為了獲取一個滾動的結果集,必須先獲得一個Statement對象,然後根據參數type,concurrency的取值情況,返回相應的類型的結果集。
Statement stmt=con.createStatement(int type,int concurrency); Request re=stmt.executeQuery(SQL語句);type取值及說明:
ResultSet.TYPE_FORWORD_ONLY 結果集的游標只能向下滾動 ResultSet.TYPE_SCROLL_INSENSITIVE 結果集的游標可以上下滾動,當數據庫變化時,當前結果集不變 ResultSet.TYPE_SCROLL_SENSITIVE 返回可滾動的結果集,當數據庫變化時,當前結果集同步改變concurrency取值及說明:
ResultSet.CONCUR_READ_ONLY 不能使用結果集更新數據庫中的表 ResultSet.CONCUR_UPDATABLE 能用結果集更新數據庫中的表滾動查詢常用方法:
public boolean previous() 將游標向上移動,當移動到結果集第1行的前面時返回false public void beforeFirst() 將游標移動到結果集的初始位置,第一行之前 public void afterLast() 將游標移動到結果集最後一行之後 public void first() 將游標移動到結果集的第一行 public void last() 將游標移動到結果集的最後一行 public boolean isAfterLast() 判斷游標是否在最後一行之後 public boolean isBeforeFirst() 判斷游標是否在第一行之前 public boolean isFirst() 判斷游標是否指向結果集的第一行 public boolean isLast() 判斷游標是否指向結果集的最後一行 public int getRow() 得到當前游標所指行的行號,行號從1開始,如果結果集沒有行,返回0 public boolean absolute(int row) 將游標移動到參數row指定的行號,如果row取負值,就是倒數的行數
使用SQL語句添加、更新、刪除紀錄。Statement對象調用public int executeUpdate(String sqlStatement)方法通過參數sqlStatement指定的方式實現向數據庫表中添加、更新、刪除紀錄。
//添加 executeUpdate("INSERT INTO user VALUES('007','邦德'); //更新 executeUpdate("UPDATE user SET name='詹姆斯·邦德'"); //刪除 executeUpdate("DELETE FROM user WHERE id='007'");
如果熟悉數據庫的DML語句,不必使用這種方式,使用結果集操作數據庫表必須先返回結果集。為了避免中文亂碼,數據的連接方式中需要加入characterEncoding=uft8或gb2312或gbk。例如:
try{ Class.forName("com.mysql.jdbc.Driver"); } catch(Exception e){ System.out.print("缺失JDBC驅動程序"); } try{ String uri="jdbc:mysql://127.0.0.1/test?"+"user=pinnsvin&password=pinnsvin&characterEncoding=utf8"; //默認端口可以省略,使用+為了使代碼清晰 con=DriverManager(uri); Statement sql=con.createStatement(ResultSet.TYPE_SCRO;;_SECSITIVE,ResultSet.CONCUR_UPDATABLE); ResultSet rs=sql.executeQuery("SELECT * FORM user"); } catch(SQLException e){ System.out.print(e); }
3.2.1.更新
使用結果集更新數據庫表中第n行記錄中某列的值:
(1)使結果集rs的游標移動到第n行
rs.absolute(n);
(2)結果集更新第n行第m列的值,可以使用下面的方法更新列值
updateInt(String columnName,int x) updateInt(int columnIndex,int x) updateLong(String columnName,long x) updateLong(int columnIndex,long x) updateDouble(String columnName,double x) updateDouble(int columnIndex,double x) updateString(String columnName,String x) updateString(int cloumnIndex,String x) updateBoolean(String columnName,Boolean x) updateBoolean(int columnIndex,Boolean x) updateDate(String columnName,Date x) updateDate(int columnIndex,Date x)(3)結果集調用updateRow方法用結果集中的第n行更新數據庫中第n行記錄
例:更新user表中第4行記錄的name列的值
rs.absolute(4); rs.updateString(2,"傑森斯坦森");//也可rs.updateString("name","傑森斯坦森"); rs.updateRow();3.2.2.插入
(1)使用moveToInsertRow()方法將結果集rs的游標移動到插入行
(2)使用updateXxx()方法更新列值
(3)結果集調用insertRow()方法用結果集中的插入行向數據庫表中插入一行新紀錄
Java提供了更高效的數據庫操作機制,就是PreparedStatement對象,也就是預處理語句對象。
當向數據庫發送一個SQL語句,數據庫庫中的SQL解釋器負責將SQL語句生成底層的內部命令,然後執行該命令,完成有關的數據操作。如果不斷的向數據庫發送SQL語句就會增加數據庫中SQL解釋器的負擔,影響執行速度。如果應用程序能針對連接的數據庫,事先將SQL語句解釋為底層的內部命令,然後直接然數據庫執行這個命令,這樣會降低解釋器的壓力,並且提高訪問速度。
使用Connection連接對象調用prepareStatement(String sql)方法對參數sql指定的SQL語句進行預編譯處理,生成該數據庫底層的內部命令,並將該命令封裝在PreparedStatement對象pre中,pre可以調用下面的方法執行內部命令:
ResultSet executeQuery()
boolean execute()
int executeUpdate()
在對SQL進行預處理時可以使用通配符“?”來代替字段的值,必須在語句執行前設置通配符代表的值。
prepareStatement pre=con.prepareStatement("SELECT * FROM user WHERE age<?"); pre.setInt(1,18);//設置第一個通配符的值為18
事務(Transaction)是並發控制的單位,是用戶定義的一個操作序列。這些操作要麼都做,要麼都不做,是一個不可分割的工作單位。事務是保證數據庫中數據完整性與一致性的重要機制。
5.2.1.setAutoCommit(boolean autoCommit)方法
使用setAutoCommit(boolean autoCommit)方法關閉自動提交模式。
因為和數據庫建立連接的對象con的提交模式是自動提交模式,即該連接con產生的Statement或PreparedStatement對象對數據庫提交任何一個SQL語句操作會立即生效。為了能進行事務處理必須關閉con的自動提交模式(默認)。
con.setAutoCommit(false);
5.2.2.Commit()方法
con調用commit()方法可以讓事務中的SQL語句全部生效。如果事務中任何一個SQL語句沒有生效,就會拋出SQLException異常。
5.2.3.rollback()方法
在處理SQLException時,con必須調用rollback()方法,它的作用是:撤銷引起數據發生變化的SQL語句操作,將數據庫中的數據恢復到commit()方法執行之前的狀態。