提綱:
1. JDBC使用快速回顧
2. 批處理
3. 事務
複習
- 怎樣註冊驅動
Class.forName("com.sql.jdbc.Driver");
2.怎樣獲取連接對象
DriverManager.getConnection(url,name,password);
url作用:通過url可以知道具體加載哪一個驅動
mysql的url可以簡寫:jdbc:myql:///mydb
- 怎樣獲取可以操作sql語句的對象
Statement st=conn.createStatement();
st.executeQuery();
st.executeUpdate();
st.execute();
PreparedStatement pst=conn.prepareStatement(sql); //佔位符是?
setXXX()
executeQuery();
pst.executeUpdate();
4.執行查詢語句後,可以得到ResultSet
ResultSet rs=st.executeQuery(sql);
rs.next();
getObject()
getInt();
5.關閉資源
rs.close();
st.close();
conn.close();
關於多數據處理.
批處理
批處理應用:一次可以執行多條sql語句
批處理有兩種方式
1.Statement
addBatch(String sql) //將多條sql語句回到批處理中
cleaarBatch(); //清空所有的sql
executetBatch(); //執行一批sql
2.PreparedStatement
addBatch(); //添加SQL語句回到批處理
executeBaatch(); //批量執行sql
Statement與PreparedStatement區別
1.Statement適合執行不同的sql語句 PreparedStatement適合執行相同的sql語句
2.Statement在執行時比PreParedStatement的效率低1
看兩個demo吧
我先把jdbc封裝到一個utils裏面
package cn.lawfree.JDBC.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
public class JdbcUtil {
private static String DRIVER;
private static String URL;
private static String USERNAME;
private static String PASSWORD;
// private static final ThreadLocal<Connection> tl = new
// ThreadLocal<Connection>();
static {
// 獲取連接數據
ResourceBundle bundle = ResourceBundle.getBundle("db");
DRIVER = bundle.getString("driver");
URL = bundle.getString("url");
USERNAME = bundle.getString("username");
PASSWORD = bundle.getString("pwd");
}
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
throw new RuntimeException("加載驅動加載驅動");
}
}
// 創建一個可以去Connection對象的方法
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
// throw new RuntimeException("獲取連接失敗");
e.printStackTrace();
}
return conn;
}
// 關閉方法Connection方法
public static void closeConnection(Connection conn) throws SQLException {
if (conn != null) {
conn.close();
}
}
// 關閉Statement方法
public static void closeStatement(Statement st) throws SQLException {
if (st != null) {
st.close();
}
}
// 關閉ResultSet方法
public static void closeResultSet(ResultSet rs) throws SQLException {
if (rs != null) {
rs.close();
}
}
}
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import cn.lawfree.JDBC.util.JdbcUtil;
//statement的批處理
public class Demo1 {
public static void main(String[] args) throws SQLException {
String sql0 = "use t_testpatch";
String sql1 = "create table user(id int,name varchar(20),sex varchar(10),age int )";
String sql2 = "insert into user values(1,'tom','male','20')";
String sql3 = "insert into user values(2,'fox','male','30')";
String sql4 = "update user set age=40 where id=1";
// 1.獲取Connection對象
Connection conn = JdbcUtil.getConnection();
// 2.獲取Statement對象
Statement st = conn.createStatement();
// 3.將sql語句添加到st中
st.addBatch(sql0);
st.addBatch(sql1);
st.addBatch(sql2);
st.addBatch(sql3);
st.addBatch(sql4);
// 4.批處理
st.executeBatch();
// 5.關閉資源
st.close();
conn.close();
}
}
package cn.lawfree.JDBC.batch;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import cn.lawfree.JDBC.util.JdbcUtil;
//PreparedStatement執行批處理
public class demo2 {
public static void main(String[] args) throws SQLException {
Connection conn = JdbcUtil.getConnection();
String sql = "insert into user values(?,?,?,?)";
PreparedStatement pst = conn.prepareStatement(sql);
for (int i = 1; i < 10; i++) {
pst.setInt(1, i);
pst.setString(2, "name" + i);
pst.setString(3, "male");
pst.setInt(4, 20 + (int) (Math.random() * 10));
// 添加到批處理
pst.addBatch();
}
// 執行
pst.executeBatch();
pst.close();
conn.close();
conn.close();
}
}
事務
通俗地講:事務是指一組操作,組成這組操作的功能,要不全部成功,要不全部不成功
關於事務
1.數據庫本意識提供事務.
2.jdbc提供對事務的處理.
1.數據庫中事務處理
mysql事務是自動提交的.------默認情況,事務自動提交,一條sql語句是一個單獨事務
oracle事務是手動提交. commit
start transaction ------開啓事務
rollback ------回滾
commit ------提交事務
mysql可以設置提交方式嗎?
show variables like ‘%commit’; 查看提交方式
set autocomit=off/on; 關閉自動提交
演示 start transaction rollback commit使用
create table acount(
id int,
name varchar(10),
money int
)
insert into account values(1,'aaa',1000);
insert into account values(2,'bbb',1000);
insert into account values(3,'ccc',1000);
aaa--匯款給-->bbb 500元
update acount set money=money-500 where name='aaa'; 從aaa前去500.
update acount set money=money+500 where name='bbb'; 給bbb加上500.
事務處理操作
1.start transcation.
2.
update acount set money=money-500 where name='aaa'; 從aaa前去500.
update acount set money=money+500 where name='bbbb'; 給bbb加上500.
3.發現數據有問題–>rollback;
4. commit
2.jdbc事務處理
在Connection中提供
setAutoCommit(boolean f); //-----設置事務的提交方式
rollback(); //-----事務回滾
commit(); //-----事務提交
這三個方法是jdbc中事務的三個方法
Savepoint 回滾點
con.setSavepoint(); 獲取(設置回滾點)
rollback(Savepoint) ;//這樣使用
還是來看一個demo
package cn.lawfree.JDBC.transaction;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//這是轉賬操作的底層實現
//包含兩個方法,存錢和取錢方法
public class AccountDao {
// 存儲
public void save(double money, String name, Connection conn)
throws SQLException {
String sql = "update account set money=money+? where name=? ";
PreparedStatement pst = conn.prepareStatement(sql);
pst.setDouble(1, money);
pst.setString(2, name);
int row = pst.executeUpdate();
if (row == 0) {
throw new RuntimeException("存款失敗");
}
pst.close();
}
// 取錢
public void get(double money, String name, Connection conn)
throws SQLException {
String sql = "update account set money=money-? where name=?";
PreparedStatement pst = conn.prepareStatement(sql);
pst.setDouble(1, money);
pst.setString(2, name);
int row = pst.executeUpdate();
if (row == 0) {
throw new RuntimeException("存款失敗");
}
pst.close();
}
}
package cn.lawfree.JDBC.transaction;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import cn.itcast.lawfree.util.JdbcUtil;
//這是轉賬支付的service操作,主要用於實現事務邏輯
//我們給它添加一個回滾的邏輯
public class AccountService {
public void hk() {
AccountDao dao = new AccountDao();
Connection conn = JdbcUtil.getConnection();
// 開啓事務 ------setAutoCommit(false);
Savepoint point = null;
try {
conn.setAutoCommit(false);
// 1.從a賬戶取錢500
dao.get(500, "aaa", conn);
// 設置一個回滾點
point = conn.setSavepoint();
// 2.向賬戶存500;
dao.save(500, "bbb", conn);
} catch (SQLException e) {
// 回滾
// rollback
try {
conn.rollback(point);
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
try {
// commit
conn.commit();
// 關閉conn
JdbcUtil.closeConnection(conn);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
事務的特性(ACID)
1.原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生
2.一致性(Consistency)
事務前後數據的完整性必須一致
3.隔離性(Isolation)
事務的隔離性是指多個用戶併發訪問數據庫時,一個用戶的事務不能被其他用戶的事務所幹擾,多個併發事務之間的數據要相互隔離
4.持久性(Durability)
持久性是指一個事務一旦被提交.它對數據庫中數據的改變是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響
*重點介紹事務的隔離性*
如果不考慮事務的隔離性會引發的問題
1. 髒讀 一個事務讀取到另一個事務的未提交數據
A 轉賬給B 100,未提交
B 查詢賬戶多了100
A 回滾
B 查詢賬戶那100不見了
2.不可重複讀 兩次讀取的數據不一致(強調的是update操作,數據的總條數不變
將隔離級別設置成 Read committed.查看是否可以解決髒讀問題
演示不可重複讀:
A 轉賬 給B 100,未提交
B 查詢 金額沒變(級別是: Read committed 避免了髒讀)
A 查詢,發現金額多了100
兩次讀取到的數據不一致,出現了不可重複讀.
- 虛讀(幻讀) 兩次讀取的數據不一致(強調的是insert操作,數據的總條數變化)
事務的隔離級別
數據庫中一共有四種隔離級別
1.Serializable:可避免髒讀 不可重複讀 虛讀情況的發生.(串行化)
2.Repeatable read:可避免髒讀 不可重複讀情況發生(輸入一個commit即可得到最新數據) .(可重複讀)不可避免虛讀
3.Read committed:可避免髒讀情況發生(讀已提交)
4.Read uncommitted:最低級別,以上情況均無法保證(讀未提交)
mysql默認的隔離級別是什麼?怎麼設置隔離級別?
mysql默認隔離級別是Repeatable read 級別
select @@tx_isolation 查詢當起事務隔離級別
set session transaction isolation level 設置事務隔離級別
set session transaction isolation level Read uncommitted;
serializable會出現鎖表情況
安全性越高的,性能越低
下面我們用mysql具體來看看不同的事務隔離級別會發生什麼.
1. 準備一個表account,用兩個Mysql打開打開,就像這樣:
2. 我們已經知道Mysql默認事務隔離級別是Repeatable read,我們先來看看能不能避免髒讀和不可重複讀:
3. 由於csdn傳圖片卡到爆?以後有空再弄……
JDBC設置事務的隔離級別
在connection接口中提供
setTransactionIsolation(int level)用來設置事務的隔離級別
四個級別字段
小結:
1.Statementment與PreparedStatement執行批處理的特點
Statement適合執行多條不同的sql
PreparedStatement適合執行相同的sql
2.事務
一組操作,要麼全部成功,要麼全不成功
3.mysql中的事務管理
1.start transcation rollback commit.
2.mysql中的事務默認是
autocommit=on 可手動修改
autocommit=off
oracle數據庫它的事務必須手動提交
4.jdbc管理事務
Connection下的
1.setAutoCommit(boolean flag)
2.rollback
3.commit
4.Savepoint回滾點
5.事務特性 (重點)
ACID
原子性 一致性 gelixing 持久性
6.隔離性
不考慮隔離性會發生什麼問題?
1.髒讀 2.不可重複讀 3虛讀(幻讀)
7.隔離級別
1.Serializable:可避免髒讀 不可重複讀 虛讀情況的發生.(串行化)
2.Repeatable read:可避免髒讀 不可重複讀情況發生(輸入一個commit即可得到最新數據) .(可重複讀)不可避免虛讀
3.Read committed:可避免髒讀情況發生(讀已提交)
4.Read uncommitted:最低級別,以上情況均無法保證(讀未提交)
8.jdbc怎樣設置事務的隔離級別
setTranscationIsolation(int level)