第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();

posted on 2018-01-31 22:57  東風★破  阅读(120)  评论(0)    收藏  举报

导航