首先糾正前一篇博客中的一個小問題,關於Get和Post兩種請求,昨天翻了下室友的Android開發教程,看了下發送請求那一塊,里面說到Get請求是想從服務端獲取信息,Post只是想上傳信息到服務端,但是有一點不明白,明明Post也有response對象,應該也能返回信息到客戶端才對,區別還是不太懂。
下面進入正題,這一篇博客主要是記錄回顧JDBC的一些操作,以及遇到的一些問題
1.准備工作
首先MySQL安裝好不用多說,然后編譯器我的是eclipse oxygen,相對上一次需要多准備的也就只有一個jar包,下載鏈接:https://dev.mysql.com/downloads/connector/j/
2.JDBC連接MySQL數據庫
我們首先來看一下官方給出的樣例代碼
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; // Notice, do not import com.mysql.cj.jdbc.* // or you will have problems! public class LoadDriver { public static void main(String[] args) { try { // The newInstance() call is a work around for some // broken Java implementations Class.forName("com.mysql.cj.jdbc.Driver").newInstance(); } catch (Exception ex) { // handle the error } } }
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; Connection conn = null; ... try { conn = DriverManager.getConnection("jdbc:mysql://localhost/test?" + "user=minty&password=greatsqldb"); // Do something with the Connection ... } catch (SQLException ex) { // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); }
以上兩段是官方給出的連接數據庫的代碼,第一部分是利用forName函數獲取MySQL驅動,后面的newInstance可以不用寫,forName中的參數是根據你MySQL的版本來的,這也就是我學習中遇到的第一個坑,最開始跟着網上的教程做一直連接不上數據庫,因為之前的MySQL版本forName中的參數都是com.mysql.jdbc.Driver,而我下的最新版本是com.mysql.cj.jdbc.Driver,獲取驅動之后就可以准備連接了Connection con = DriverManager.getConnection(String url),這一步只需要知道url的值就可以了,下面就講一講url的格式
url: "jdbc:mysql://" + 數據庫所在的ip(本機就可以用localhost)+ "/" + 想要訪問的數據庫名 + "?" + "user=" + 數據庫賬號 + "&password=" + 賬號對應的密碼
其實一般的訪問的url鏈接也是跟這個差不太多的,這部分放到后面再繼續說,不管怎么說連接數據庫的部分算是結束了吧,畢竟根據官方的文檔來寫應該是沒什么問題的,然而讓我萬萬沒想到的,就是有問題!
這個的原因是時差,報錯的信息中也有寫到time zone對吧,所以網上查一查也就知道了,在url后面接上&serverTimezone=GMT就真正的連接成功啦,特別提醒url中不能有空格,所以像我這種寫代碼習慣數字和操作符用空格隔開的朋友需要注意。
3.利用JDBC對數據庫進行操作
首先來介紹一下JDBC對數據庫進行操作的方式,目前就我了解到的就兩種類,一個是Statement類,一個是PreparedStatement類
先來介紹第一個Statement
1)Statement對象的創建方式
我們之前通過DriverManager.getConnection()函數已經獲得了Connection對象con,而Statement對象則是通過con.createStatement()函數獲得的,下面是官方的解釋
返回類型為Statement,作用生成一個Statement對象來發送SQL聲明給數據庫
2)利用Statement對象進行數據庫查詢
數據庫查詢用到的函數是executeQuery(String SQL),其實也很好理解,execute是執行的意思,query是查詢的意思,這里函數返回的是一個ResultSet對象
ResultSet的常用的操作就是next()函數和各種get函數,前一個是移動到下一行,如果后面沒有了就返回false,有就返回true,get函數就比如getString、getInt等,傳參的方式有int string兩種,比如我user表中的是id(int)、username(String)、password(String),在執行ResultSet rs = execute("SELECT * FROM user")之后,我想獲得第一行中的username就先rs.next();然后可以用String str = rs.getString(2);或者rs.getString("username");同樣的想獲得id可以使用int id = rs.getInt(1)或者rs.getInt("id");下面給出官方的說明
3)利用Statement對象對數據庫進行增、刪、改操作
在JDBC中update、delete、insert都被歸納成update,所以都通過executeUpdate(String sql)函數進行操作,返回值是操作的行數,這個就沒什么好說的了,下面是官方的說明文檔
4)在不知道是查詢還是更改的情況下
在不知道是要查詢還是更改的情況下,我們可以用execute(String sql)直接執行,但是這個函數的返回值是bool型,也就是在sql為查詢語句的時候就返回true,在為更改語句的時候返回false,如果是查詢語句,想要獲得結果可以在Statement對象調用execute()函數之后再調用getResultSet()函數;如果是update語句,想要得到update的列數,可以可以在Statement對象調用execute()函數之后再調用getUpdateCountt()函數,下面是例子
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.sql.ResultSet; // assume that conn is an already created JDBC connection (see previous examples) Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT foo FROM bar"); // or alternatively, if you don't know ahead of time that // the query will be a SELECT... if (stmt.execute("SELECT foo FROM bar")) { rs = stmt.getResultSet(); } // Now do something with the ResultSet .... } catch (SQLException ex){ // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } finally { // it is a good idea to release // resources in a finally{} block // in reverse-order of their creation // if they are no-longer needed if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { } // ignore rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { } // ignore stmt = null; } }
到這里有關Statement的操作就講解完畢,Statement的操作一般針對用不變的操作,輸入的語句是固定的,不要說用String拼接,那樣不安全比如固定好的語句為
String sql = "SELECT password FROM user WHERE username=" +user_name;
針對這種情況輸入的是'OR'1'='1'時,執行的語句就發生了變化,所以針對Statement對象不要使用字符串拼接!
那么要實現可以復用、更改的執行語句要用什么呢,下面就介紹第二種PreparedStatement
1)創建PreparedStatement
創建PreparedStatement對象的方式為con.prepareStatement(String sql)
String sql = "SELECT password FROM user WHERE username=?";
PreparedStatement ps = con.prepareStatement(sql);
?就是未定的部分(注意=的左右不要有空格,不要有空格,不要有空格),可以利用ps.setString(int num,String str)函數拼接上去,但是利用這個函數拼接就不會出現問題,因為這個函數會把敏感符號全部轉譯,單引號這種符號也就只是一個單引號了,不會改變原來SQL語句的意思,還有一些setInt等操作、作用也是一樣的
這里的第一個參數就表示是第幾個?,第二個參數是要修改的值
2)利用PreparedStatement對象對數據庫進行查詢操作
由於在創建PreparedStatement對象的時候傳入的sql語句,所以查詢的時候就不需要額外傳入參數了,直接調用executeQuery()函數即可,返回值仍然是ResultSet型
3)利用PreparedStatement對象對數據庫進行增、刪、改
同查詢值要直接調用executeUpdate()函數即可,返回值還是更改的行數
以上就是我掌握的JDBC的知識,這段時間在學習過濾器和監聽器的操作,大概十天之后寫關於這兩個的操作吧