第3.29课 上课 JDBC深入介绍, 事务处理, 批处理
3_29

JDBC深入介绍
事务处理
数据库事务概念
事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。
事务处理的常用方法
void setAutoCommit(boolean autoCommit) throws SQLException
说明:将此连接的自动提交模式设置为给定状态。如果连接处于自动提交模式下,则它的所有 SQL 语句将被执行并作为单个事务提交。否则,它的 SQL 语句将聚集到事务中,直到调用 commit 方法或 rollback 方法为止。默认情况下,新连接处于自动提交模式。
void commit() throws SQLException
说明:使所有上一次提交/回滚后进行的更改成为持久更改。
void rollback() throws SQLException
说明:取消在当前事务中进行的所有更改。
void rollback(Savepoint savepoint) throws SQLException
说明:取消所有设置给定 Savepoint 对象之后进行的更改。 此方法只应该在已禁用自动提交时使用。
事务隔离级别
1.Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
2.Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
3.Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
4.Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
实例
/**
* 事务实例
* 两个操作要做成一个事务
* 注意:事务必须在一个连接中。
*
*/
public class TransferTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstm = null;
Savepoint sp = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/fkit";
conn = DriverManager.getConnection(url, "root", "root");
//开启事务
conn.setAutoCommit(false);
String sql1 = "update t_user set username = 'tiger' where id = 1";
pstm = conn.prepareStatement(sql1);
pstm.executeUpdate();
//设置事务还原点
sp = conn.setSavepoint();
String sql2 = "update t_user set username = 'tiger2' where id = 2";
pstm = conn.prepareStatement(sql2);
pstm.executeUpdate();
//运行这条语句时候程序会出错
System.out.println(8/0);
//提交事务
conn.commit();
System.out.println("数据正常提交");
} catch (Exception e) {
e.printStackTrace();
try {
//回滚事务
//conn.rollback();
//回滚到指定的还原点位置
conn.rollback(sp);
System.out.println("异常发生,数据回滚");
conn.commit();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
finally{
try {
if (pstm != null) {
pstm.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
批处理
示例代码1:
conn.setAutoCommit(false); //设置事务为手动
ps = conn.prepareStatement("delete from user where id=?");
for(String id : ids){
ps.setInt(1, Integer.parseInt(id));
ps.addBatch();//使用批处理方式提高效率
}
//更新数据库操作
int[] flag = ps.executeBatch();
//提交事务
conn.commit();
return (flag.length > 0) ? true : false;
----------------------------------------------------
示例代码2:
conn = connectionFactory.getConnection();
String sql = "insert into t_user(name,email,birthday) values(?,?,?,?)";
ps = conn.prepareStatement(sql);
for(int i=0; i < 10000; i++){
ps.setString(1, "name" + i);
ps.setString(2, "name" + i + "@yayadou.com");
ps.setDate(3, new Date());
ps.addBatch();
if(i % 500 == 0){
ps.executeBatch();
ps.clearBatch();
}
}
ps.executeBatch();
ps.clearBatch();
浙公网安备 33010602011771号