JDBC高级使用和数据库事务

JDBC批处理操作:

批量处理允许您将相关的SQL语句分组到批处理中,并通过对数据库的一次调用提交它们。

当一次向数据库发送多个SQL语句时,可以减少连接数据库的开销,从而提高性能。

 

使用Statement对象进行批处理操作:

以下是使用语句对象的批处理的典型步骤序列

  • 使用createStatement()方法创建Statement对象。

  • 使用setAutoCommit()将auto-commit设置为false 。

  • 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。

  • 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。

  • 最后,使用commit()方法提交所有更改。

// Create statement object
Statement stmt = conn.createStatement();

// Set auto-commit to false
conn.setAutoCommit(false);

// Create SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
             "VALUES(200,'Zia', 'Ali', 30)";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);

// Create one more SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
             "VALUES(201,'Raj', 'Kumar', 35)";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);

// Create one more SQL statement
String SQL = "UPDATE Employees SET age = 35 " +
             "WHERE id = 100";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);

// Create an int[] to hold returned values
int[] count = stmt.executeBatch();

//Explicitly commit statements to apply changes
conn.commit();

 

PrepareStatement对象进行批处理:

  1. 使用占位符创建SQL语句。

  2. 使用prepareStatement() 方法创建PrepareStatement对象。

  3. 使用setAutoCommit()将auto-commit设置为false 。

  4. 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。

  5. 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。

  6. 最后,使用commit()方法提交所有更改。

// Create SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
             "VALUES(?, ?, ?, ?)";

// Create PrepareStatement object
PreparedStatemen pstmt = conn.prepareStatement(SQL);

//Set auto-commit to false
conn.setAutoCommit(false);

// Set the variables
pstmt.setInt( 1, 400 );
pstmt.setString( 2, "Pappu" );
pstmt.setString( 3, "Singh" );
pstmt.setInt( 4, 33 );
// Add it to the batch
pstmt.addBatch();

// Set the variables
pstmt.setInt( 1, 401 );
pstmt.setString( 2, "Pawan" );
pstmt.setString( 3, "Singh" );
pstmt.setInt( 4, 31 );
// Add it to the batch
pstmt.addBatch();

//add more batches

//Create an int[] to hold returned values
int[] count = stmt.executeBatch();

//Explicitly commit statements to apply changes
conn.commit();


数据库事务:

一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元。

 

事务的四大特点(ACID)

  • actomicity(原子性)

    表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败

  • consistency(一致性)

    表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态

  • isolation(隔离性)

    事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。

  • durability(持久性)

    持久性事务完成之后,它对于系统的影响是永久性的。

 

事务隔离级别

  SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

Read Uncommitted(读取未提交内容)

​ 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

Read Committed(读取提交内容)

​ 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

Repeatable Read可重读

​ 这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable 可串行化​ 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

​ 这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。

例如:

​   脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

​   不可重复读(Non-repeatableread):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

​   幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的

mysql中事物的控制:begin;执行sql;出错了 rollback;没有出错: commit;

 

Java中事务应用:

如果JDBC连接处于自动提交模式,默认情况下,则每个SQL语句在完成后都会提交到数据库。

事务使您能够控制是否和何时更改应用于数据库。它将单个SQL语句或一组SQL语句视为一个逻辑单元,如果任何语句失败,则整个事务将失败。

要启用手动事务支持,而不是JDBC驱动程序默认使用的自动提交模式,请使用Connection对象的setAutoCommit()方法。如果将boolean false传递给setAutoCommit(),则关闭自动提交。我们可以传递一个布尔值true来重新打开它。

事务的提交和回滚 :

 

try{
   //Assume a valid connection object conn
   conn.setAutoCommit(false);
   Statement stmt = conn.createStatement();
   
   String SQL = "INSERT INTO Employees  " +
                "VALUES (106, 20, 'Rita', 'Tez')";
   stmt.executeUpdate(SQL);  
   //Submit a malformed SQL statement that breaks
   String SQL = "INSERTED IN Employees  " +
                "VALUES (107, 22, 'Sita', 'Singh')";
   stmt.executeUpdate(SQL);
   // If there is no error.
   conn.commit();
}catch(SQLException se){
   // If there is any error.
   conn.rollback();
}

1、要取消掉JDBC的自动提交:void setAutoCommit(boolean autoCommit)

2、执行各个SQL语句,加入到批处理之中

3、如果所有语句执行成功,则提交事务 commit();如果出现了错误,则回滚:rollback()

try {
	 connection.setAutoCommit(false);
	 add(connection);
//			int i = 1/0;
			sub(connection);
			System.out.println("===============");
			connection.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("---------------");
			try {
				connection.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
		    }
      }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值