jdbc(java database connectivity)爲java開發者使用數據庫提供了統一的編程接口,它由一組java類和接口組成。java
JDBC須要用到的類和接口有:mysql
DriverManager、Connection、Statement、ResultSet sql
本機的mysql版本是5.7.26 win32的,因此本章訪問mysql都以該版本爲例:數據庫
而後進入https://dev.mysql.com/downloads/connector/j/下載mysql-connector-java.jar包,用於鏈接mysql編程
以下圖所示,只有8.0.19版本,那咱們下載它就行了,反正無論64位仍是32位都能訪問:工具
下載解壓後,就有個mysql-connector-java-8.0.19.jar:測試
接下來就來測試,能不能訪問url
3.JDBC使用過程spa
3.1 經過DriverManager. registerDriver(Driver driver)來註冊驅動程序code
須要注意,new Driver的時候,須要選擇com.mysql.cj.jdbc.Driver:
由於com.mysql.jdbc.Driver已經被棄用了.
PS:也能夠直接將DriverManager. registerDriver(Driver driver)改成:
Class.forName("com.mysql.cj.jdbc.Driver"); //加載一下這個類就能夠註冊驅動,由於mysql Driver類的靜態代碼塊中已經調用了registerDriver()來註冊驅動程序.
3.2 而後經過 Connection DriverManager.getConnection(String url, String user, String password)來鏈接數據庫,並獲取Connection對象
url: 填入「jdbc:子協議://ip地址:端口號/數據庫名」 ,若是是mysql則填入「jdbc:mysql://localhost:3306/數據庫名」
針對mysql-connector-java-8.0以上的版本,則還要追加"?characterEcoding=utf-8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"
username:mysql用戶名
password:mysql密碼
3.3 經過Connection對象獲取statement對象
Statement statement = connection.createStatement();
3.4 經過statement對象的executeQuery(String)來執行查詢sql語句,並返回ResultSet數據庫結果集
好比:
ResultSet resultSet = statement. executeQuery("select * from student"); //獲取student表裏的數據
除此以外還有int executeUpdate(String sql)方法.用來實現INSERT、UPDATE 或 DELETE 語句,返回值表示執行sql語句以後影響到的數據行數 (後面示例有講)
3.5 而後經過ResultSet來讀出query內容
ResultSet經常使用方法以下:
boolean first(); //移到內容第一行數據處 boolean last(); //移到內容最後一行數據處 int getRow() ; //獲取當前光標處於的行號 boolean isLast() //獲取光標是否位於此 ResultSet 對象的最後一行。 boolean next(); //移到下一行數據處,而後就能夠經過getXXX()獲取完當前一行數據後,則經過next()來移動到下行繼續getXXX(),直到next()返回爲false爲止 boolean previous(); //移到上一行數據處 String getString(String columnLabel); //獲取當前一行的columnLabel列名的內容 String getString(int columnIndex); //獲取當前一行的第columnIndex列的內容,第一列是從1開始的. String getInt (String columnLabel); //獲取當前一行的columnLabel列名的內容 String getInt(int columnIndex); //獲取當前一行的第columnIndex列的內容,第一列是從1開始的. //...除此以外,還有getFloat(),getLong(),getShort(),getURL(),getBoolean(),getRowId()
PS:獲取到ResultSet後,必須先next()一次才能getXXX(),來獲取內容
3.6 訪問結束後,釋放Mysql資源(畢竟mysql連入個數是有限的)
try { if(resultSet!=null){ resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(connection!=null){ connection.close(); } } catch (SQLException e) { e.printStackTrace(); }
4.本章要訪問的數據庫以students爲例:
5.首先來寫JdbcUtils工具類
JdbcUtils工具類裏主要寫getConnection(),releaseResc()這兩個類,這樣避免後續的重複代碼產生.
JdbcUtils.java代碼以下所示:
public class JdbcUtils { private static String driver; private static String url; private static String user; private static String pwd; static{ driver = "com.mysql.cj.jdbc.Driver"; url = "jdbc:mysql://localhost:3306/students?characterEcoding=utf-8&" + "useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"; user = "root"; pwd = "sql"; } //獲取一個連接mysql的Connection對象 static public Connection getConnection(){ try { Class.forName(driver); Connection connection = DriverManager.getConnection(url,user,pwd); return connection; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 釋放Mysql資源(畢竟mysql連入個數是有限的) * @param resultSet 結果集 * @param statement * @param connection 連接 */ public static void releaseResc(ResultSet resultSet, Statement statement, Connection connection) { try { if(resultSet!=null){ resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(connection!=null){ connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
6.數據庫查詢示例
查詢全部學生的信息:
@Test public void jdbcQuery(){ ResultSet resultSet = null; Statement statement = null; Connection connection = null; try { connection = JdbcUtils.getConnection(); //經過JdbcUtils獲取connection statement = connection.createStatement(); String sql = "select * from student"; resultSet = statement.executeQuery(sql); while(resultSet.next()){ String name = resultSet.getString("name"); String score = resultSet.getString("score"); String classs = resultSet.getString("class"); System.out.println("姓名:"+name+" 成績:"+score+" 班級:"+classs); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { JdbcUtils.releaseResc(resultSet, statement, connection); //釋放資源 } }
打印以下所示:
7.數據庫插入示例
@Test public void jdbcInser(){ ResultSet resultSet = null; Statement statement = null; Connection connection = null; try { connection = JdbcUtils.getConnection(); statement = connection.createStatement(); String name = "小f"; int score = 99; String classs = "初2-4班"; String sql = "INSERT INTO student(name,score,class) " +" values('"+name+"','"+String.valueOf(score)+"','"+classs+"')"; int result = statement.executeUpdate(sql); //executeUpdate:用來實現INSERT、UPDATE 或 DELETE 語句,返回值表示執行sql語句以後影響到的數據行數 System.out.println("插入了"+result+"條數據"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { JdbcUtils.releaseResc(resultSet, statement, connection); //釋放資源 } }
運行打印:
查看數據庫:
8.數據庫更新示例
將全部低於60分的同窗的成績改成0:
@Test public void jdbcUpdate(){ ResultSet resultSet = null; Statement statement = null; Connection connection = null; try { connection = JdbcUtils.getConnection(); statement = connection.createStatement(); String sql = "update student SET score='0' WHERE score<60"; int result = statement.executeUpdate(sql); //executeUpdate:用來實現INSERT、UPDATE 或 DELETE 語句,返回值表示執行sql語句以後影響到的數據行數 System.out.println("更新了"+result+"條數據"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { JdbcUtils.releaseResc(resultSet, statement, connection); //釋放資源 } }
查看數據庫:
9.SQL 注入攻擊
Statement採起直接編譯 SQL 語句的方式,扔給數據庫去執行,因此很容易進行被SQL注入攻擊.
好比:
咱們登錄執行時須要執行:
statement.executeQuery("select id from users where name ='"+username+"' and password = '"+password+"'");
而黑客則將字符串直接改成:
statement.executeQuery("select id from users where name ='"+username+"' or '1==1' and password = '"+password+"'");
就能夠直接亂輸入密碼也能實現登陸了,因此java中提供了另外一個類PreparedStatement, 採用"?"佔位符預編譯,再填充參數,用來避免SQL注入攻擊.
PreparedStatement類介紹
採用"?"佔位符預編譯,再填充參數,而後經過setXXX()來填充參數.好比setString():
setString(int parameterIndex, String x); //向第parameterIndex個佔位符填入x內容 // parameterIndex:第一個?佔位符是1,第二個是2.... //...除了該方法以外,還有setFloat(),setLong(),setBoolean()....等等
修改登陸界面之PreparedStatement使用以下所示:
public static boolean login(String username,String password){ Connection connection = JdbcUtils.getConnection(); //獲取 try { String sql = "select id from users where username =? and password = ?"; //要運行的sql語句,經過?來替換登陸帳號和密碼 PreparedStatement preparedStatement = connection.prepareStatement(sql); //第一個? 用username字符串去替換 preparedStatement.setString(1, username); //第二個? 用password字符串去替換 preparedStatement.setString(2, password); ResultSet resultSet = preparedStatement.executeQuery(); return resultSet.next(); //有值則返回true,不然返回false; } catch (SQLException e) { e.printStackTrace(); return false; } }