Jdbc進階(四)
***************************資料庫的隔離級別****************************
mysql 資料庫 這4種隔離級別都支援 預設的隔離級別 可重複讀
oracle 只支援 讀已提交、序列化 預設的隔離級別是 讀已提交
一.讀未提交
會出現髒讀
客戶端A 修改了資料 沒提交 ,其他客戶端也可以讀到,讀未提交....
髒讀: 經理(客戶端A)發工資 本來要發5000,不小心多打1個0,發了50000,但是沒提交,
客戶端B(楊帆)一查,可以查到,挺高興,剛準備去消費,消費的路上,經理馬上反應過來了,立馬回滾
從新插入一條5000的記錄,楊帆再一查5000,資料不一致, 這種不一致的現象叫做髒讀...
讀的是臨時的不準確的資料!!!
***************************批量更新****************************
每次呼叫 executeUpdate() 執行一條SQL語句 都要通過網路 把sql語句傳送到資料庫伺服器 再返回
效率比較低
可以把多條語句 加入到 Batch裡, executeBatch() 就把這些sql語句 都發送伺服器端一起執行了,效率高
返回值是int[]
JDK8.0新增的功能
long count = stmt.executeLargeUpdate();//如果一條sql語句影響行數比較多 超過int型別的表數範圍 使用這個方法
同樣批量更新時 如果每條sql語句 影響的行數 都超過int型別表數範圍 使用
long[] longArr = stmt.executeLargeBatch();
演示程式碼:
public void testBatchUpdate() {
Statement stmt = null;
try {
String sql1 = "insert into account values(1,'楊帆1',1000)";
String sql2 = "insert into account values(2,'楊帆2',2000)";
String sql3 = "insert into account values(3,'楊帆3',3000)";
String sql4 = "insert into account values(4,'楊帆4',4000)";
stmt = conn.createStatement();
boolean autoCommit = conn.getAutoCommit();
conn.setAutoCommit(false);
// 收集多條SQL語句 等待一起傳送
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
stmt.addBatch(sql4);
int[] countArr = stmt.executeBatch();
for (int i = 0; i < countArr.length; i++) {
System.out.println("第" + i + "條SQL語句受影響的行數為:" + countArr[i]);
}
conn.commit();
conn.setAutoCommit(autoCommit);
System.out.println("批量更新成功");
} catch (SQLException e) {
try {
conn.rollback();
System.out.println("批量更新失敗");
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("建立通道失敗");
e.printStackTrace();
} catch (Exception e) {
try {
conn.rollback();
System.out.println("批量更新失敗");
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("建立通道失敗");
e.printStackTrace();
} finally {
// 五.關閉
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
System.out.println("關閉pstmt通道失敗");
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("關閉資料庫連線失敗");
e.printStackTrace();
}
}
}
***************************資料庫連線池****************************
一.為什麼使用資料庫連線池
每次執行增刪改查操作的時候 都要從新建立連線、關閉連線,比較耗時,效率低.為了提高效率,有了資料庫連線池的概念
二.什麼是資料庫連線池
在應用程式(或web伺服器)啟動的時候, 事先建立好n個數據庫連線物件,並把這些物件放到一個容器中,以備使用.這個容器
叫做資料庫連線池. 使用者用的時候 不需要建立連線,直接從連線池中取出一個Connection物件來用就可以了,用完以後也不需要
關閉,直接把Connection物件 還到資料庫連線池中..大大的減少了頻繁建立、關閉連線所浪費的時間.
javax.sql.DataSource 資料來源 它是一個介面 不同產生有對該介面的不同實現,常見的第三方資料來源
1.DBCP
2.C3P0
三.如何使用
DBCP
匯入兩個jar包
commons-dbcp.jar
commons-pool.jar
commons-dbcp.jar 依賴於 commons-pool.jar
package com.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.dbcp.BasicDataSource;
/**
* 公司:藍橋軟體學院
* 作者:zhangzy
* 時間:2017年9月1日 下午5:31:26
* 功能:資料庫連線池 DBCP實現
*/
public class ConnOracleDataSource {
private static BasicDataSource dataSource = new BasicDataSource();
private static String driverClassName = "oracle.jdbc.OracleDriver";
private static String url = "jdbc:oracle:thin:@localhost:1521:orcl";
private static String username = "scott";
private static String password = "tiger";
static{
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
//1.設定Conn物件的初始個數
dataSource.setInitialSize(5);
//2.設定最大的活動連線數
dataSource.setMaxActive(20);
//3.設定最少空閒數
dataSource.setMinIdle(2);
}
public static Connection getConnection(){
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
System.out.println("建立連線失敗");
e.printStackTrace();
}
return conn;
}
public static void closeConnection(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
System.out.println("關閉通道失敗");
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
System.out.println("關閉資料庫連線失敗");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
System.out.println(ConnOracleDataSource.getConnection());
}
}
測試效率:
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 1; i <= 100; i++) {
CategoryDaoImpl dao = new CategoryDaoImpl();
Category category = new Category();
category.setCname("手機");
category.setCdesc("通訊工具");
dao.addCategory(category);
}
long endTime = System.currentTimeMillis();
System.out.println("總共使用了" + (endTime - startTime) + "毫秒");
}