在實際開發工做中,有關於jdbc的應用,常常性地會出現如下五個問題:java
增長或修改查詢語句來優化查詢結果mysql
eg.:讀取數據庫表中全部的記錄,千萬級的記錄的讀取可能會出現java的內存溢出異常OutOfMemoryErrorsql
緣由分析:java程序是運行在java虛擬機中的,jvm是有內存大小限制的,當咱們把大量的記錄一次性地讀入jvm的內存中的時候,讀出的數據若是超出了jvm所規定的內存最大值的時候就會出現內存溢出的錯誤。數據庫
解決辦法:既然內存容量是有限的,咱們能夠讀取一部分數據進行處理,處理完畢以後在進行下一部分數據的讀取,這樣避免一次性地載入過多的數據致使內存的溢出。jvm
在jdbc中是如何具體實現的呢?優化
遊標的開啓:編碼
須要在加載驅動後,得到與數據庫的鏈接的同時需啊喲啊在url後面加上?useCursorFetch=trueurl
表示咱們對這個數據庫的讀取須要使用遊標spa
要是使用有標的話,必須使用PreparedStatement 的setFetchSize();code
入參爲int型的整數,表示jdbc從數據庫中一次讀取記錄的數量,須要在查詢executeQuery以前須要設置一次查詢的記錄的數量。
import java.sql.*; public class Test001 { private String driver = "com.mysql.jdbc.Driver"; private String url = "jdbc:mysql://host:port/dataBaseName"; private String userName = "xxx"; private String passWord = "xxx"; public void Test() { Connection connection = null; String sql = null; PreparedStatement prepareStatement = null; ResultSet rs = null; try { //裝載驅動 Class.forName(driver); //獲取鏈接 connection = DriverManager.getConnection(url,userName,passWord); //變動url設置 url = url + "userCursorFecth = true"; //sql語句 sql = "select * from tableName where sex = Female"; //執行sql語句 prepareStatement = connection.prepareStatement(sql); //設置遊標讀取參數 prepareStatement.setFetchSize(1); //執行查詢語句,返回結果集 rs = prepareStatement.executeQuery(); //取結果集 while(rs.next()) { System.out.println(rs.getString(1)); } //此時的執行結果的按照設置的參數進行結果的操做,一條條地處理 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (null != connection) connection.close(); if (null != rs) rs.close(); if (null != prepareStatement) prepareStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
讀取的每一條記錄中包含大字段的內容,在實際開發過程當中,爲了方便管理,每每數據記錄會包含大字段的內容,讀取可能會出現內存溢出。
處理方式:流方式讀取
jdbc的實現:
rs = prepareStatement.executeQuery(); //取結果集 while(rs.next()) { System.out.println(rs.getString(1)); InputStream in = rs.getBinaryStream(1); File file = new File(File_URL); OutputStream out = null; out = new FileOutputStream(file); int temp = 0; while ((temp = in.read()) != -1) { out.write(temp); } in.close(); out.close(); }
海量的數據插入,若是一條條的插入,每一次的sql語句的發送與接收都須要時間
更加高效的使用方式爲
批處理:
發送一次sql 插入多條語句
Statement提供了三個接口:
addbatch()
executeBatch()
clearBatch()
遍歷須要插入的元素,將其放入batch中,而後執行executeBatch最後執行clearBatch()。
Set<String> users = new HashSet<String>(); String user1 = "zhangsan"; String user2 = "lisi"; String user3 = "zhaowu"; users.add(user1); users.add(user2); users.add(user3); Statement statement = connection.createStatement(); String sql2 = "insert into tableName(user)values("; for (String user : users) { statement.addBatch(sql + user + ")"); } statement.executeBatch(); statement.clearBatch();
涉及到中文,須要注意可能出現的亂碼問題
能夠設置不一樣級別的代碼:server級別,database級別,table級別, 字段級別,
優先級依次增大,好比設置列級別的編碼,那麼其餘三個就不會生效。
咱們須要設置jdbc的編碼方式來適應數據庫的編碼方式,設置方式也很簡單,須要在url中增長
例如 : url = url +"characterEncoding=utf8";