JDBC和連線池使用步驟
從實習到現在已經快一年啦,學習了很多也遺忘了很多,最近有空所以把以前的筆記整理一下放到部落格上。
JDBC:java database connectivity
JDBC定義一套標準介面,即訪問資料庫的通用API,不同的資料庫廠商根據各自資料庫的特點去實現這些介面,實現介面、類:驅動:由資料庫廠商實現
-JDBC是java應用程式和資料庫之間的通訊橋樑,是java應用程式訪問資料庫的通道
-JDBC標準主要由一組介面組成,其好處是統一了各種資料庫訪問方式
-JDBC介面的實現類稱為資料庫驅動,由各個資料庫廠商提供,使用JDBC必須匯入這個驅動!一定知道驅動是什麼!
connection只是介面,真正的實現是由資料庫廠商提供的驅動包
一、JDBC主要由一大堆介面組成:這些介面的實現類是由驅動提供的,Oracle驅動就是這些介面的實現類
JDBC使用步驟:
1、匯入JDBC驅動
-使用Maven可以便捷地匯入資料庫驅動
1、註冊JDBC驅動
-引數:“驅動程式類名”
-Class.forname("驅動程式類名")
3、獲得Connection物件
- 需要三個引數:url,username,password - 連線到資料庫
4、建立Statement(語句)物件
-conn.getStatemnent()方法建立物件
-用於執行SQL語句 -注意語句空格
-execute(ddl)執行任何SQL,常用於執行DDL、DCL
-executeUpdate(dml)執行DML語句,如:insert,update,delete
-executeQuery(dql) 執行DQL語句,如:select
5處理執行結果:
-execute(ddl)如果沒有異常則成功 boolean
-executeUpdate(dml)返回數字,表示更新“行”數量,丟擲異常則失敗 int
-executeQuery(dql)返回ResultSet(結果)物件,代表2維查詢結果, ResultSet
使用for遍歷處理,如果查詢失敗丟擲異常
6、關閉資料連線!!!關閉資料連線
-conn.close();
二、關於執行計劃
*.java源程式編譯成計算機可以看懂的*.class位元組碼;SQL語句翻譯成執行計劃才能執行
①、Statement主要用於執行靜態SQL語句,即內容固定不變的SQL語句;Statement每執行一次都要對傳入的SQL語句編譯一次,效率較差;沒有引數用Statement的話比preparedStatement快一點
②、PreparedStatement物件用於執行帶引數的預編譯執行計劃;可以重複使用執行計劃,提高DB效率,可以重用執行計劃,而且可以執行多次;可以避免注入攻擊。
1、任何SQl都是先編譯“執行計劃”,再執行“執行計劃”
2、資料庫為了優化效能,在SQL語句完全一樣的情況下,會重用執行計劃
-執行計劃編譯較慢
-重用執行計劃可以提高資料庫效能
3、資料庫只在SQL語句完全一樣的情況下,才會重用執行計劃
-如果SQL語句中有一個字元的更改,也會執行不同的執行計劃
-一個空格或者一個大小寫不同也會建立不同的執行計劃
使用步驟:
1、將帶引數的SQL傳送到資料庫建立執行計劃
2、替換執行計劃中的引數
3、執行執行計劃,得到結果
三、資料庫連線池
資料庫連線池是管理併發訪問資料庫連線的理想解決方案
解決併發問題;資料庫的併發有限,限制連線數,避免資料庫崩潰;重用資料庫連線
Apahce DBCP
連線池是建立和管理連線的緩衝池技術,將連線準備好被任何需要他們的應用使用
DriverManager管理資料庫連線適合單執行緒情況,而在多執行緒併發情況下,為了能夠重用資料庫連線,同時控制併發連線總數,保護資料庫避免連線過載,一定要使用資料庫連線池
###使用DBCP連線池
資料庫連線池的開源實現非常多,DBCP是其中之一。
使用DBCP:1、匯入連線池jar
2、建立連線池物件
3、設定資料庫必須的連線引數
4、設定可選的連線池管理策略引數
5、從連線池中獲得活動的資料庫連線
6、使用連線範圍資料量
7、使用以後關閉資料庫連線,這個關閉不再是真的關閉連線,而是將使用過的連線歸還給連線池
連線管理工具類:
public class DBUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
private static int initSize;
private static BasicDataSource ds; //連線池就一個
static {
ds = new BasicDataSource();
Properties cfg = new Properties();
//初始化靜態屬性
//利用properties 讀取配置檔案
//從配置檔案中查詢相應引數
try { //load天生有異常
InputStream in = DBUtils.class.getClassLoader()
.getResourceAsStream("db.properties");
cfg.load(in);
driver = cfg.getProperty("jdbc.driver");
url = cfg.getProperty("jdbc.url");
username = cfg.getProperty("jdbc.username");
password = cfg.getProperty("jdbc.pasaword");
initSize = Integer.parseInt(cfg.getProperty("initSize"));
in.close();
//初始化連線池
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
//設定連線池的管理策略引數
ds.setInitialSize(initSize);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static Connection getConnection() {
try {
//getConnection()從連線池獲取重用的連線,如果連線池滿了,則等待
//如果連線歸還,則獲取重用的連線; 連線池的執行緒阻塞方法
Connection conn = ds.getConnection();
return conn;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void close(Connection conn) {
try {
//將用過的連線歸還到連線池
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void rollback(Connection conn) {
try {
//將用過的連線歸還到連線池
if (conn != null) {
conn.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
其配套引數設定檔案 db.propwerties:
#db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/checkaccount?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.pasaword=
#paramter for BasicDataSourse
initSize=2
四、事務處理
資料庫提供了事務控制功能,支援ACID特性
JDBC提供了API,方便地呼叫資料庫的事務功能,其方法有:
-Connection.getAutoCommit():獲得當前事務的提交方式,預設是true
-Connection.setAutoCommit():設定事務的提交屬性,引數是true:自動提交;false:不自動提交,取消自動提交,後續手動提交
-Connection.Commit():提交事務
-Connection.rollback():回滾事務
標準呼叫事務的模板以及執行計劃使用步驟:
public static void dbTest() {
Connection conn = null;
try {
conn = DBUtils.getConnection();
conn.setAutoCommit(false);
//業務處理 執行計劃使用步驟
String sql = "insert into test_wcx values( ?,?,?)";
// 1、將帶引數的SQL傳送到資料庫建立執行計劃
PreparedStatement ps = conn.prepareStatement(sql);
//2、替換執行計劃中的引數
ps.setInt(1, 2);
ps.setString(2, "weicx");
ps.setString(3, "test");
//3、執行執行計劃,得到結果
int result = ps.executeUpdate();
System.out.println(result);
conn.commit();
} catch (Exception e) {
e.printStackTrace();
DBUtils.rollback(conn);
} finally {
DBUtils.close(conn);
}
}
事務Transaction:保證交易可靠
比如轉賬:扣除跟增加必須在一個事務中完成
事務特性ACID:
原子性:表示不可再分單元,最小單元,事務必須都是原子工作單元;對於其資料修改,要麼全都執行,要不全都不執行
一致性:事務在完成時,必須使所有的資料都保持一致狀態
隔離性:由併發事務所做的修改必須與任何其他併發事務所做的隔離 不能被幹擾
永續性:事務完成之後,它對於系統的影響是永久性的
隔離有級別:
最低級別:修改一個可以看一個
現在學的是提交以後可以看,別人修改過程中可以看,看的是修改過程之前的資料:幻讀,是不真實的
最高級別:就是別人修改過程中看都不能看
事務是資料庫的概念,JDBC支援事務,本質還是在資料庫中實現的
有在資料庫中沒有提交的事務 Java中操作會卡住(恩?卡住?)。