JavaEE之JDBC進階使用
JDBC
JDBC批處理
1、為什麼需要批處理?
之前:一次操作只能傳送一條sql語句到資料庫伺服器,效率並不高!如果要插入2000條記錄,那麼必須傳送2000條sql語句。
如果IO流的話,一次寫出一個位元組,顯然效率效率並不高,所以可以使用快取位元組陣列提高每次寫出的效率。
現在:插入2000條記錄,但現在使用sql快取區,一次傳送多條sql到資料庫伺服器執行。這種做法就叫做批處理。
2、JDBC批處理的API
statement 批處理:
void addBatch(String sql) 將sql語句新增到緩衝區
int[] executeBatch() 執行批處理命令 傳送所有的sql語句
void clearBatch() 清空快取區
PreparedStatement批處理:
void addBatch() 新增引數到快取區
int[] executeBatch() 執行批處理命令。 傳送所有快取區的sql
void clearBatch() 清空sql快取區
現進行測試:
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Statement; /** * 同時插入2000條資料 * @author APPle * 結論: * 1) mysql資料庫不支援PreparedStatement優化,而且不支援批處理優化 * 2) oracle資料庫即支援PreparedStatement優化,也支援批處理優化 * */ public class Demo1 { public static void main(String[] args) { //testByStaement(); //testByStaementBatch(); //testByPreparedStaement(); //testByPreparedStaementBatch(); testTime(); } /** * 測試執行速度 */ public static void testTime(){ long start = System.currentTimeMillis(); //testByStaement(); //testByStaementBatch(); //testByPreparedStaement(); testByPreparedStaementBatch(); long end = System.currentTimeMillis(); System.out.println("耗時為:"+(end-start)); } /** * 沒有批處理的Statement的情況 * mysql: 耗時為:7838 oracle:耗時為:6580 */ public static void testByStaement(){ Connection conn = null; Statement stmt = null; try{ conn = JdbcUtil.getConnection(); stmt = conn.createStatement(); for(int i=1;i<=2000;i++){ stmt.executeUpdate("INSERT INTO student VALUES("+i+",'張三',20,'男')"); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtil.close(stmt, conn); } } /** * 使用批處理的Statement的情況 * mysql: 耗時為:9097 oracle:耗時為:5477 */ public static void testByStaementBatch(){ Connection conn = null; Statement stmt = null; try{ conn = JdbcUtil.getConnection(); stmt = conn.createStatement(); for(int i=1;i<=2000;i++){ //把sql新增到快取區 stmt.addBatch("INSERT INTO student VALUES("+i+",'張三',20,'男')"); //每20條傳送sql if(i%20==0){ //執行批處理命令 stmt.executeBatch(); //清空快取區 stmt.clearBatch(); } } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtil.close(stmt, conn); } } /** * 沒有批處理的PrepaedStatement的情況 * mysql: 耗時為:9051 oracle:耗時為:4161 */ public static void testByPreparedStaement(){ Connection conn = null; PreparedStatement stmt = null; try{ conn = JdbcUtil.getConnection(); stmt = conn.prepareStatement("INSERT INTO student VALUES(?,?,?,?)"); for(int i=1;i<=2000;i++){ //引數賦值 stmt.setInt(1, i); stmt.setString(2, "張三"); stmt.setInt(3, 20); stmt.setString(4, "男"); //執行 stmt.executeUpdate(); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtil.close(stmt, conn); } } /** * 使用批處理的PrepaedStatement的情況 * mysql:耗時為:9379 oracle: 耗時為:1391 */ public static void testByPreparedStaementBatch(){ Connection conn = null; PreparedStatement stmt = null; try{ conn = JdbcUtil.getConnection(); stmt = conn.prepareStatement("INSERT INTO student VALUES(?,?,?,?)"); for(int i=1;i<=2000;i++){ //引數賦值 stmt.setInt(1, i); stmt.setString(2, "張三"); stmt.setInt(3, 20); stmt.setString(4, "男"); //把引數新增到快取區 stmt.addBatch(); //每20次傳送一次引數 if(i%20==0){ //執行批處理命令 stmt.executeBatch(); //清空快取區的引數 stmt.clearBatch(); } } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtil.close(stmt, conn); } } }
測試結論:
1) mysql資料庫不支援PreparedStatement優化,而且不支援批處理優化
2) oracle資料庫即支援PreparedStatement優化,也支援批處理優化3、JDBC讀取大檔案資料
mysql:
字串:varchar char 65535
大文字資料: tinytext , longtext ,text
位元組: bit
大位元組檔案:tinyblob(255byte),blob(64kb),MEDIUMBLOB(約16M) longblob(4GB)
oracle:
字串: varchar2 char 65535
大文字資料: clob
位元組: bit
大位元組檔案: blob3.1 JDBC操作字元檔案
/**
* 對大文字資料處理
* @author APPle
*
*/
public class Demo1 {
/**
* 檔案儲存到資料中
*/
@Test
public void testWrite(){
Connection conn = null;
PreparedStatement stmt = null;
try{
//獲取連線
conn = JdbcUtil.getConnection();
//建立PreparedStatement
String sql = "INSERT INTO test1(content) VALUES(?)";
stmt =conn.prepareStatement(sql);
//設定引數
/**
* 引數一: 引數位置
* 引數二: 輸入字元流
*/
/**
* 讀取本地檔案,返回輸入字元流
*/
FileReader reader = new FileReader(new File("e:/Demo1.java"));
stmt.setClob(1, reader);
//執行sql
int count = stmt.executeUpdate();
System.out.println("影響了"+count+"行");
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 從資料中讀取文字內容
*/
@Test
public void testRead(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
//獲取連線
conn = JdbcUtil.getConnection();
String sql = "SELECT * FROM test1 where id=?";
stmt = conn.prepareStatement(sql);
//設定引數
stmt.setInt(1, 2);
//執行sql,返回結果集
rs = stmt.executeQuery();
if(rs.next()){
//方式一:當做字串取出資料
/*
String content = rs.getString("content");
System.out.println(content);
*/
//方式二:返回輸入流形式
Clob clob = rs.getClob("content");
Reader reader = clob.getCharacterStream();
//寫出到檔案中
FileWriter writer = new FileWriter(new File("e:/Demo2.java"));
char[] buf = new char[1024];
int len = 0;
while( (len=reader.read(buf))!=-1){
writer.write(buf, 0, len);
}
//關閉流
writer.close();
reader.close();
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(conn, stmt, rs);
}
}
}
3.2 JDBC操作位元組檔案
/**
* 對位元組檔案處理
* @author APPle
*
*/
public class Demo2 {
/**
* 檔案儲存到資料庫中
*/
@Test
public void testWrite(){
Connection conn = null;
PreparedStatement stmt = null;
try{
//獲取連線
conn = JdbcUtil.getConnection();
String sql = "insert into test2(content) values(?)";
stmt = conn.prepareStatement(sql);
//設定引數
/**
* 引數一:引數位置
* 引數二:輸入位元組流
*/
/**
* 讀取本地檔案
*/
InputStream in = new FileInputStream(new File("e:/abc.wmv"));
//stmt.setBlob(1, in);
stmt.setBinaryStream(1, in);
//執行
stmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 注意: mysql資料庫預設情況下,只能儲存不超過1m的檔案,由於max_allowed_packet變數的限制
* 可以修改: %mysql%/my.ini檔案, 修改或新增max_allowed_packet變數,然後重啟mysql即可!!
*/
/**
* 從資料中讀取位元組內容
*/
@Test
public void testRead(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
//獲取連線
conn = JdbcUtil.getConnection();
String sql = "SELECT * FROM test2 where id=?";
//獲取PreparedStatement
stmt = conn.prepareStatement(sql);
//設定引數
stmt.setInt(1, 1);
//執行sql
rs = stmt.executeQuery();
if(rs.next()){
//返回輸入流
//InputStream in = rs.getBinaryStream("content");
InputStream in = rs.getBlob("content").getBinaryStream();
//寫出檔案中
FileOutputStream out = new FileOutputStream(new File("e://3.jpg"));
byte[] buf = new byte[1024];
int len = 0;
while((len=in.read(buf))!=-1){
out.write(buf, 0, len);
}
//關閉流
out.close();
in.close();
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(conn, stmt, rs);
}
}
}