JDBC的作用
JDBC為java訪問數據庫提供通用的API,可以為多種關系數據庫提供統一訪問。因為SQL是關系式數據庫管理系統的標准語言,只要我們遵循SQL規范,那么我們寫的代碼既可以訪問MySQL又可以訪問SQL Server.
簡單的說,JDBC可以做三件事:
- 與數據庫建立連接
- 發送SQL語句
- 處理結果
JDBC中重要的類
java.sql.DriverManager:用來加載不同的JDBC驅動程序並且為創建的新的數據庫連接提供支持;
java.sql.Connection:完成對某一指定數據庫的連接功能;java.sql.Statement:在一個已經創建的連接(java.sql.Connection)中作為執行SQL語句的容器;它包含了兩個重要的子類:
java.sql.PreparedStatement:用於執行預編譯的SQL語句;
java.sql.CallableStatement:用於執行數據庫中已經創建好的存儲過程(Stored Procedure)。
java.sql.ResultSet:代表特定SQL語句執行后的數據庫結果集。
這些類我們可以參考JDK API,里面有非常詳細的說明。並且是中文的^_^
與數據庫建立連接(mysql)
1.URL
JDBC URL的標准語法如下下所示。他們之間由冒號分隔:
<協議jdbc>:<子協議>:<子名稱>
<協議>:JDBC URL中的協議總是jdbc。
<子協議>:驅動程序名或數據庫連接機制的名稱。例如:mysql
<數據源>:包含要連接數據庫的主機、端口、名稱、用戶名、密碼等信息。
例如mysql連接的URL格式為:
jdbc:mysql//[hostname][:port]/[dbname][?param1=value1][¶m2=value2]….
有一點說明,mysql端口號(port)可以通過如下方式查詢:
mysql>show global variables like 'port';
2.使用DriverManager管理驅動類
Class.forName("com.mysql.jdbc.Driver");
3.連接管理
設置不自動提交:conn.setAutoCommit(false);
提交數據:conn.commit();
回滾數據:conn.rollback();
設置自動提交:conn.setAutoCommit(true)。
關閉連接:conn.close();
下面是一個測試連接SQL的例子:
發送SQL"show databases",並顯示結果。
public static void testConn() throws SQLException { Connection conn = getConn("root", "", ""); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("show databases"); while (rs.next()) { System.out.println(rs.getString("")); }
stmt.close();//顯示關閉Statement對象,釋放資源
conn.close();
//關閉數據庫連接,這是個好習慣。盡管在程序運行結束會自動關閉。但web應用是不會結束運行的。 }
與數據庫建立連接
public static Connection getConn(String username, String password, String DBname) { String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/" + DBname; Connection conn = null; try { Class.forName(driver); conn = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; }
DatabaseMetaData-數據庫的信息
創建一個DatabaseMetaData對象
DatabaseMetaData datameta=conn.getMetaData();
1.獲取數據庫中各個表的情況
ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]);
catalog指的是數據庫
schemaPattern是數據庫的用戶
tableNamePattern是表名
types指的是table、view等
getTables方法返回一個ResultSet對象,每一條記錄是對一個表的描述。只有那些符合參數要求的表才被返回。結果集的每一行有8個字段,其中第三個為表名稱。
獲取數據庫中的表名字
public static String[] getTableNames(String DBname, Connection conn) { String[] tables = null; try { DatabaseMetaData DBmeta = conn.getMetaData(); String types[] = { "TABLE" }; ResultSet rs = DBmeta.getTables(DBname, null, null, types); List<String> ls = new ArrayList<String>(); int i = 0; while (rs.next()) { ls.add(rs.getString(3)); i++; } tables = new String[i]; ls.toArray(tables); } catch (SQLException e) { e.printStackTrace(); } return tables; }
2. 獲取表中各列的信息
ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String types[]);
getColumns返回一個ResultSet類的對象,其中每一行是對一個字段的描述,只有符合參數要求的列才被返回。
每一行的字段信息為:數據庫名、數據庫擴展名、表名、字段名
獲取表的所有字段名字
public static String[] getFieldsNames(String tableName, Connection conn) { String[] fields = null; try { DatabaseMetaData DBmeta = conn.getMetaData(); ResultSet rs = DBmeta.getColumns(null, null, tableName, null); List<String> ls = new ArrayList<String>(); int i = 0; while (rs.next()) { ls.add(rs.getString(4)); i++; } fields = new String[i]; ls.toArray(fields); } catch (SQLException e) { e.printStackTrace(); } return fields; }
3. 獲取關於索引的信息
ResultSet getIndexInfo(String catalog, String schema, Boolean unique, boolean approximate);
getIndexInfo方法返回一個ResultSet類的對象,其中每一行是對一個索引的描述,只有符合參數要求的索引才被返回。
Statement提交SQL
Statement對象發送SQL語句
Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
Statement接口提供了三種執行SQL的語句的方法:
- 方法executeQuery:用於產生單個結果集的語句,例如 SELECT 語句。
- 方法executeUpdate:用於執行 INSERT、UPDATE 或 DELETE 語句以及SQL DL(數據定義語言)語句,例如CREATE TABLE和DROP TABLE。INSERT、UPDATE或DELETE語句的效果是修改表中零行或多行中的一列或多列。executeUpdate的返回值是一個整數,指示受影響的行數(即更新計數)。對於CREATE TABLE或DROP TABLE等不操作行的語句,executeUpdate的返回值總為零。
- 方法execute:用於執行返回多個結果集、多個更新計數或兩者組合的語句。
當生成 ResultSet 對象的 Statement 對象關閉、重新執行或用來從多個結果的序列獲取下一個結果時,該 Statement 對象將自動關閉 ResultSet 對象。這意味着在重新執行Statement對象之前,需要完成對當前ResultSet對象的處理。
stmt.close();顯式關閉Statement對象,釋放DBMS資源。
結果集Resultset對象
1.ResultSet遍歷
一個ResultSet對象對應着一個由查詢語句返回的一個表,這個表中包含所有的查詢結果。實際上,我們就可以將一個ResultSet對象看成一個二維表。對ResultSet對象的處理必須逐行進行,而對每一行中的各個列,可以按任何順序進行處理。
- 行與光標:ResultSet 對象具有指向其當前數據行的光標。最初,光標被置於第一行之前。next 方法將光標移動到下一行;因為該方法在 ResultSet 對象沒有下一行時返回 false,所以可以在 while 循環中使用它來迭代結果集。
- 取得列:在對每一行進行處理時,可以對各個列按任意順序進行處理。不過,按從左到右的順序對各列進行處理可以獲得較高的執行效率。ResultSet類的getXXX()方法可以從某一列中獲得檢索結果。其中XXX是JDBC中的Java數據類型,如int、String、Date等。
ResultSet提供兩種方法來指定列進行檢索:
一種是以一個int值作為列的索引,另一種是以一個String對象作為列名來索引。第一種效率更高。
下面是變量結果集的例子:
Statement statement=conn.createStatement(); //在Connection對象的基礎上創建Statemetn對象 String sql="SELECT int_colmn, string_colmn,date_colmn," +" byte_colmn FROM table_name"; ResultSet result=statement.executeQuery(sql); //用Statement對象執行SQL語句,返回結果集 while(result.next()) { int int_value=result.getInt(1); String string_value=result.getString("colmn2"); Date date_value=result.getInt(3); Byte byte_value[]=result.getString("colmn4"); //從數據庫中以兩種不同的方式取得數據 out.println(int_value+" "+string_value+" "+date_value+" "); //將檢索結果在用戶瀏覽器上輸出 }
2.獲取結果集的信息
ResultsetMetaData rsdata=resultset.getMetaData();
GetMetaData()方法返回一個ResultSetMetaData類的對象,使用該類的方法,得到許多關於結果集的信息,下面給出幾個常用的方法:
(1) getColumnCount():返回一個int值,指出結果集中的列數;
(2) getColumnLabel(int column):返回column所指的列的顯示標題,field的SQL AS的值;
(3) getColumnName(int column):返回的是field的原始名字。可以把此方法返回的String對象作為Resultset類的getXXX()方法的參數。不過,並沒有太大的實際意義;
(4) getColumnType(int comlumn):返回指定列的SQL數據類型。它的返回值是一個int值。在java.sql.Types類中有關於各種SQL數據類型的定義;
(5) getColumnTypeName(int comlumn):返回指定列的數據類型在數據源中的名稱。它的返回值是一個String對象;這個比較常用。
(6) isNullable(int column):返回一個boolean值,指出該列是否允許存入一個NULL 值。
獲取表各個字段的信息
// LinkedHashMap保留插入順序 public static LinkedHashMap<String, String> getFields(String tableName, Connection conn) { LinkedHashMap<String, String> fields = new LinkedHashMap<>(); String sql = "select * from " + tableName; Statement stmt; try { stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); ResultSetMetaData rsmeta = (ResultSetMetaData) rs.getMetaData(); int count = rsmeta.getColumnCount(); for (int i = 1; i <= count; i++) { fields.put(rsmeta.getColumnLabel(i),rsmeta.getColumnTypeName(i)); } } catch (SQLException e) { e.printStackTrace(); } return fields; }