Java學習之jdbc加強

一、批處理

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{
			//釋放資源
			
		}
	}
}















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章