數據庫操做是程序設計中十分重要的一個部分,Java內置JDBC來操做數據庫
java
JDBC——Java Database connecting Java數據庫鏈接;本質上JDBC定義了操做數據庫的一套接口,做爲應用程序的開發人員來講只須要建立接口對應的對象便可,而接口的實現由各個數據庫廠商去完成。要在應用程序中使用JDBC,須要根據數據庫的不一樣導入對應的jar包。sql
使用步驟以下:數據庫
在使用JDBC以前須要先註冊驅動,也就是告訴JDBC,咱們須要導入哪一個jar包,這個工做由DriverManager對象來實現,能夠調用它裏面的方法 registerDriver 來實現,該方法的定義以下:apache
static void registerDriver(Driver driver);
這個方法須要傳入一個driver 對象,driver對象是具體的數據庫廠商來實現,後續相關操做實際上是根據這個driver對象來調用相關代碼,實現同一套接口操做不一樣數據庫數組
咱們查閱相關實現類的代碼以下:函數
public class Driver extends NonRegisteringDriver implements java.sql.Driver { // // Register ourselves with the DriverManager // static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } /** * Construct a new driver and register it with DriverManager * * @throws SQLException * if a database error occurs. */ public Driver() throws SQLException { // Required for Class.forName().newInstance() } }
在Driver對象中發現,它在靜態代碼塊中執行了registerDriver方法,也就是說咱們只要加載對應的類,類就會自動幫助咱們進行註冊的操做。因此在第一步註冊驅動的代碼中能夠這樣寫:學習
Class.forName("org.mariadb.jdbc.Driver"); //加載對應的Driver類到內存中
註冊了驅動以後就是獲取數據庫的鏈接對象,在DriverManager中使用getConnection方法獲取,它的定義以下:優化
static Connection getConnection(String url); static Connection getConnection(String url, Properties info); static Connection getConnection(String url, String user, String password);
上述3個方法中,經常使用的是第3個,參數分別爲: 鏈接字串、用戶名、密碼
鏈接字串的格式爲: jdbc:數據庫類型://數據庫IP:端口/數據庫名稱,好比 jdbc:mariadb://localhost:3306/testui
獲取鏈接字串的代碼以下:url
Connection conn = DriverManager.getConnection("jdbc:mariadb://localhost:3306/study", "root", "root");
獲取鏈接對象以後,須要向數據庫傳遞sql語句並執行它,執行sql語句須要使用對象 Statement, 經常使用的方法以下:
boolean execute(String sql); ResultSet executeQuery(String sql); int executeUpdate(String sql);
通常可使用execute來執行相關操做,若是是查詢語句,可使用executeQuery來執行並獲取返回的結果集,若是須要執行DELTE、UPDATE、INSERT等語句可使用executeUpdate來更新數據庫
咱們能夠經過 Connection對象的createStatement方法獲取一個Statement對象,代碼以下:
Statement statement = conn.createStatement(); String strSql = "INSERT INTO student VALUES(2, '2b', 28, 78.9, '2017-12-30', NULL)"; statement.execute(strSql); statement.close(); //最後別忘了關閉對象
若是咱們執行了像insert、delete、update等等語句,可能不須要關注具體的返回結果,可是若是使用的是select語句,則須要獲取返回的結果
獲取select語句返回的結果可使用 executeQuery 方法,該方法會返回一個結果集對象
能夠將結果集對象想象成一個二維的數組,保存了查詢到的相關數據,每一行表明一條數據,行中的每一列是一個字段的數據。結果集中使用遊標來遍歷每一行數據。使用get相關函數來獲取對應索引的數據。一行遍歷完了使用next移動到下一行;其中get相關方法主要有:
Blob getBlob(int columnIndex); Blob getBlob(String columnLabel); boolean getBoolean(int columnIndex); boolean getBoolean(String columnLabel); byte getByte(int columnIndex); byte getByte(String columnLabel); byte[] getBytes(int columnIndex); byte[] getBytes(String columnLabel); Date getDate(int columnIndex); Date getDate(int columnIndex, Calendar cal); Date getDate(String columnLabel); Date getDate(String columnLabel, Calendar cal); double getDouble(int columnIndex); double getDouble(String columnLabel); float getFloat(int columnIndex); float getFloat(String columnLabel); int getInt(int columnIndex); int getInt(String columnLabel); long getLong(int columnIndex); long getLong(String columnLabel);
在獲取告終果以後須要關閉對應對象清理資源,這部分只須要調用對應的cloase方法便可
最終一個完整的demo 以下:
public class JDBCDemo1 { public static void main(String[] args) { Connection conn = null; Statement statement = null; ResultSet resultSet = null; try { Class.forName("org.mariadb.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mariadb://localhost:3306/test", "root", "root"); String sql = "select * from student"; statement = conn.createStatement(); resultSet = statement.executeQuery(sql); while (resultSet.next()){ int id = resultSet.getInt(1); //注意:這裏面的索引是從1開始的 String name = resultSet.getString(2); int age = resultSet.getInt(3); double score = resultSet.getDouble(4); Date birthday = resultSet.getDate(5); Timestamp insertTime = resultSet.getTimestamp(6); System.out.println(id + "\t" + name + "\t" + age + "\t" + score + "\t" + birthday + "\t" + insertTime); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { try{ if (resultSet != null){ resultSet.close(); } if (statement != null){ statement.close(); } if (conn != null){ conn.close(); } }catch (SQLException e){ e.printStackTrace(); } } } }
咱們知道使用sql拼接的方式來執行sql語句容易形成sql注入漏洞,即便針對某些關鍵字進行過濾也很難消除這個漏洞,一旦存在sql注入,那麼數據庫中的數據很容易就會被黑客竊取。而使用參數化查詢的方式能夠從根本上消除這個漏洞。
jdbc中參數化查詢使用的對象是 PreparedStatement, 它與Statement對象不一樣在於,它會提早將sql語句進行編譯,後續只會接收固定類型的參數;而Statement只會簡單的去執行用戶輸入的sql語句。
在進行參數化查詢的時候須要先準備sql語句,可是在查詢參數中須要使用 ? 作標記,表示這個位置是一個參數,後續在真正執行前再傳入,好比說能夠準備這樣的sql語句 update student set score = 100 where name = ?
。
準備好sql語句以後,須要設置對應參數位置的值,咱們可使用 setXxx 方法來設置,setXxx 方法與以前介紹的get方法相似,根據不一樣的數據類型 Xxx 有不一樣的取值。
設置完參數以後,與Statement 同樣,調用對應的execute方法來執行便可.
String sql = "update student set score = 100 where name = ?"; ps = conn.prepareStatement(sql); ps.setString(1, "2b"); ps.executeUpdate();
在須要頻繁操做數據庫的應用中,使用數據庫鏈接池技術能夠對數據庫操做進行必定程度的優化。原理請自行百度。
若是要本身實現數據庫鏈接池須要實現 javax.sql.DataSource 的getConnection方法。固然我學習Java只是爲了學習一下Web相關的內容,並不想太過於深刻,因此天然不會去管怎麼實現的,只要調用第三方實現,而後使用就行了。
常見的開源的第三方庫有: Apache commons-dbcp、C3P0 、Apache Tomcat內置的鏈接池(apache dbcp)、druid(由阿里巴巴提供)。
本着支持國產的心態,此次使用的主要是 druid。
druid 鏈接池須要提供一個配置文件來保存數據庫的相關內容
driverClassName=org.mariadb.jdbc.Driver url=jdbc:mariadb://localhost:3306/study username=root password=masimaro_1992 # 初始化時鏈接池中保留鏈接數 initialSize=5 # 最大鏈接數 maxActive=10 # 最大時間,超過這個時間沒有任何操做則會關閉鏈接 maxWait=3000
在使用時主要須要以下步驟:
相關代碼以下:
Connection conn = null; Statement statement = null; Properties properties = new Properties(); try { properties.load(JDBCDemo3.class.getResourceAsStream("druid.properties")); DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); conn = dataSource.getConnection(); statement = conn.createStatement(); //do something } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }