一、批處理
1、原因:提高jdbc操作效率,一次發送多條SQL到數據庫服務器執行
2、方法(API):
(1)Statement批處理:
主要方法:
void addBatch(String sql) 添加sql到緩存區(暫時不發送)
int[]executeBatch() 執行批處理命令。 發送所有緩存區的sql
voidclearBatch() 清空sql緩存區
(3)PreparedStatement批處理:
主要方法:
voidaddBatch() 添加參數到緩存區
int[]executeBatch() 執行批處理命令。 發送所有緩存區的sql
voidclearBatch() 清空sql緩存區
舉例:
1、往一張表中插入2000條數據:
分別使用了Statement批處理和PreparedStatement批處理
和不使用批處理的這兩個方法進行對比:
package com.deu.a.statement.preparedstatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import com.jdbc.c.util.JdbcUtil;
public class Demo {
public static void main(String[] args) {
long starttime = System.currentTimeMillis();
//testStatemet();//不使用批處理忘數據庫學生表中插入2000條數據//76268
//testStatementBatch();//使用批處理//3837
//testPreparedment();//採用預編譯,不使用批處理//72041
testPreparedmentBatch();//使用批處理//4321
long endtime = System.currentTimeMillis();
System.out.println(endtime-starttime);
}
private static void testPreparedmentBatch() {
Connection conn = null;
PreparedStatement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "INSERT INTO student VALUES(?,?);";
//獲取statement對象
stmt = conn.prepareStatement(sql);
for (int i = 1; i <= 2000; i++) {
stmt.setInt(1, i);
stmt.setString(2, "hello");
stmt.addBatch();
if (i%20==0) {
///執行sql語句
stmt.executeUpdate();
//清空緩存
stmt.clearBatch();
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
//釋放資源
JdbcUtil.close(conn, stmt, null);
}
}
private static void testPreparedment() {
Connection conn = null;
PreparedStatement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "INSERT INTO student VALUES(?,?);";
//獲取statement對象
stmt = conn.prepareStatement(sql);
for (int i = 1; i <= 2000; i++) {
stmt.setInt(1, i);
stmt.setString(2, "hello");
stmt.executeUpdate();
}
}catch(Exception e){
e.printStackTrace();
}finally{
//釋放資源
JdbcUtil.close(conn, stmt, null);
}
}
private static void testStatementBatch() {
Connection conn = null;
Statement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
//獲取statement對象
stmt = conn.createStatement();
//給數據庫發送2000次sql語句
//每次給stmt中存儲添加20條數據
for (int i = 1; i < 2000; i++) {
String sql = "INSERT INTO student VALUES("+i+",'hello');";
//先將這個sql暫時添加到stmt中
stmt.addBatch(sql);
if (i%20==0) {
//批量發送sql
stmt.executeUpdate(sql);
//清空stmt緩衝區
stmt.clearBatch();
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
//釋放資源
JdbcUtil.close(conn, stmt, null);
}
}
private static void testStatemet() {
Connection conn = null;
Statement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
//獲取statement對象
stmt = conn.createStatement();
//給數據庫發送2000次sql語句
for (int i = 1; i < 2000; i++) {
String sql = "INSERT INTO student VALUES("+i+",'hello');";
stmt.executeUpdate(sql);
}
}catch(Exception e){
e.printStackTrace();
}finally{
//釋放資源
JdbcUtil.close(conn, stmt, null);
}
}
}
二、jdbc獲取自增長值
package com.deu.b.getautocreament;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import com.jdbc.c.util.JdbcUtil;
/**
* 獲取自增長值
*需求:在給部門表插入一條數據的同時,再給員工表中剛剛插入的該部門插入一條員工數據
* 1.給部門表中插入一個新的部門“財務部”
* 2.獲取財務部對應的id
* 3.給員工表中插入一條員工數據,對應的部門就是財務部對應的id
*/
public class Demo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
//創建兩條sql語句
//創建給部門表添加數據
String sql1 = "insert into dept(name) values(?);";
String sql2 = "insert into employee(name,deptId) values(?,?);";
try{
conn = JdbcUtil.getConnection();
//先給部門表中插入數據
//PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)throws SQLException
//創建一個默認 PreparedStatement 對象,該對象能獲取自動生成的鍵
//Statement.RETURN_GENERATED_KEYS: 可以返回自動增長值
//Statement.NO_GENERATED_KEYS: 不能返回自動增長值
stmt = conn.prepareStatement(sql1, Statement.RETURN_GENERATED_KEYS);
//設置參數
stmt.setString(1, "後勤部");
//提交數據
stmt.executeUpdate();
//獲取自增長的鍵值
rs = stmt.getGeneratedKeys();
int deptId = 0;
while (rs.next()) {
deptId = rs.getInt(1);
}
//給員工表添加數據
stmt = conn.prepareStatement(sql2);
stmt.setString(1, "咋打");
stmt.setInt(2, deptId);
stmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
//釋放資源
JdbcUtil.close(conn, stmt, rs);
}
}
}
三、jdbc處理大數據文件
字符:
普通存儲字符字段: mysql: char(0-255) varchar(0-65535) 長度有限的。 65535
大容量的字符字段:
mysql: text(64K) longtext(4G字符內容)
oracle: clob longclob
字節:
mysql: blob(65kb) mediumblob(16mb) longblog(4GB)
oracle: blob
舉例:
1、jdbc操作字符文件
將任意一篇文章存儲到數據庫:
package com.deu.c.club;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.jdbc.c.util.JdbcUtil;
public class ClubDemo {
public static void main(String[] args) {
//寫入數據
//write();
//讀取數據
readerd();
}
private static void readerd() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
//創建預編譯sql對象
String sql = "select * from test;";
//創建PreparedStatement
stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery();
while (rs.next()) {
Reader reder = rs.getCharacterStream(2);
FileWriter fw = new FileWriter("a.java");
char[] cha = new char[1024];
int len;
while ((len=reder.read(cha))!=-1) {
fw.write(cha, 0, len);
fw.flush();
}
//關流
fw.close();
reder.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtil.close(conn, stmt, rs);
}
}
private static void write() {
Connection conn = null;
PreparedStatement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
//創建PreparedStatment
//創建預編譯sql語句
String sql = "insert into test values(?,?);";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
stmt.setClob(2, new FileReader("Demo.java"));
stmt.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
}finally{
//釋放資源
JdbcUtil.close(conn, stmt, null);
}
}
}
2、jdbc操作字節文件
把一張圖片存儲到數據庫
package com.deu.c.club;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.jdbc.c.util.JdbcUtil;
public class BlubDemo {
public static void main(String[] args) {
//存入圖片
//writeDemo();
//讀取圖片
readerDemo();
}
private static void readerDemo() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
//獲取連接
conn = JdbcUtil.getConnection();
//創建sql預編譯對象
String sql = "select * from ad";
//創建PreparedStatement
stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery();
while (rs.next()) {
InputStream bs = rs.getBinaryStream(2);
FileOutputStream fos = new FileOutputStream("c.jpg");
//數據庫默認要求,寫入文件的大小是1m,如果存入數據庫的文件大於這個容量就會拋出異常
//com.mysql.jdbc.PacketTooBigException
//max_allowed_packet
byte[] bch = new byte[1024];
int len;
while ((len=bs.read(bch))!=-1) {
fos.write(bch, 0, len);
}
//關流
bs.close();
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//釋放資源
}
}
private static void writeDemo() {
Connection conn = null;
PreparedStatement stmt = null;
try {
//獲取連接
conn = JdbcUtil.getConnection();
//創建sql預編譯對象
String sql = "insert into ad values(?,?)";
//創建PreparedStatement
stmt = conn.prepareStatement(sql);
//設置值
stmt.setInt(1, 1);
stmt.setBlob(2, new FileInputStream("3.jpg"));
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
//釋放資源
}
}
}
四、數據庫事務
1、事務概念:就是把多條SQL語句看做一個事務,那麼這個事務要麼一起成功,要麼一起失敗
2、mysql事務操作命令:
set autocommit =0 / 1; 設置是否自動提交事務1: 表示自動提交事務,每執行一條sql語句,自動提交事務。 0: 表示關閉自動提交事務。
commit; 提交事務,一旦提交事務不能回滾
rollback; 回滾事務。回滾到事務的起始點。
3、jdbc事務操作
Connection.setAutoCommit(false) 開啓事務
Connection.commit(); 成功執行,最後提交事務
Connection.rollback(); 一旦遇到錯誤,回滾事務
4、事務的特性:
原子性:要麼一起成功,要麼一起失敗
一致性:數據庫應該從一個一致性的狀態到另一個一致性的狀態,保持不變
隔離性:多個事務直接應該可以相互隔離
持久性:事務一旦提交,應該擁擠保持下來
舉例:
銀行轉賬:
package com.deu.d.autocommit;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.jdbc.c.util.JdbcUtil;
public class Demo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement stmt = null;
String sql1 = "UPDATE blank SET balance=balance-2000 WHERE id=1;";
String sql2 = "UPDATE blank SET balance=balance+2000 WHERE id=2;";
try{
//獲取連接
conn = JdbcUtil.getConnection();
//開啓事務
conn.setAutoCommit(false);//等價於set autocommit=0;
//預編譯sql1
stmt = conn.prepareStatement(sql1);
//執行sql
stmt.executeUpdate();
//發生異常
//int i = 100/0;
stmt = conn.prepareStatement(sql2);
stmt.executeUpdate();
//提交事務
conn.commit();
}catch (Exception e) {
e.printStackTrace();
try {
//如果發生失誤就回滾
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}finally{
//釋放資源
}
}
}