JDBC事务管理

在学习JDBC事务管理过程中,我们会为事务管理是否同步感觉困惑。
这里详细讲述下mysql和oracle的事务管理模式
1、mysql的事务管理
事务的特性:
事务有以下四个标准属性的缩写ACID,通常被称为:

原子性: 确保工作单元内的所有操作都成功完成,否则事务将被中止在故障点,和以前的操作将回滚到以前的状态。

一致性: 确保数据库正确地改变状态后,成功提交的事务。

隔离性: 使事务操作彼此独立的和透明的。

持久性: 确保提交的事务的结果或效果的系统出现故障的情况下仍然存在。
在MySQL中,事务开始使用COMMIT或ROLLBACK语句开始工作和结束
当一个成功的事务完成后,发出COMMIT命令应使所有参与表的更改才会生效。

如果发生故障时,应发出一个ROLLBACK命令返回的事务中引用的每一个表到以前的状态。
可以控制的事务行为称为AUTOCOMMIT设置会话变量。如果AUTOCOMMIT设置为1(默认值),然后每一个SQL语句(在事务与否)被认为是一个完整的事务,并承诺在默认情况下,当它完成。 AUTOCOMMIT设置为0时,发出SET AUTOCOMMIT =0命令,在随后的一系列语句的作用就像一个事务,直到一个明确的COMMIT语句时,没有活动的提交。

事务隔离模式

SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE



隔离模式

   READ UNCOMMITTED
不隔离SELECT
其他事务未完成的修改(未COMMIT),其结果也考虑在内

   READ COMMITTED
把其他事务的 COMMIT 修改考虑在内
同一个事务中,同一 SELECT 可能返回不同结果

   REPEATABLE READ(默认)
不把其他事务的修改考虑在内,无论其他事务是否用COMMIT命令提交过
同一个事务中,同一 SELECT 返回同一结果(前提是本事务,不修改)

   SERIALIZABLE
和REPEATABLE READ类似,给所有的SELECT都加上了 共享锁

查看当前的隔离级别:select @@tx_isolation;
设置当前mysql连接的隔离级别:
-set transaction isolation level read committed;
设置数据库系统全局隔离级别:
-set global transaction isolation level read committed;



这里可以参考JAVA的JDBC事务编写代码进行学习

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;


public class TestTransaction {

/**
* 测试事务的隔离级别 在 JDBC 程序中可以通过 Connection 的 setTransactionIsolation 来设置事务的隔离级别.
*/
@Test
public void testTransactionIsolationUpdate() {

Connection connection = null;

try {
connection = JDBCTools.getConnection();
connection.setAutoCommit(false);//事务提交设置为非自动提交,默认为自动提交

String sql = "UPDATE users SET balance = "
+ "balance - 500 WHERE id = 1";
update(connection, sql);

connection.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {

}
}

@Test
public void testTransactionIsolationRead() {
String sql = "SELECT balance FROM users WHERE id = 1";
Integer balance = getForValue(sql);
System.out.println(balance);
}

// 返回某条记录的某一个字段的值 或 一个统计的值(一共有多少条记录等.)
public <E> E getForValue(String sql, Object... args) {

// 1. 得到结果集: 该结果集应该只有一行, 且只有一列
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try {
// 1. 得到结果集
connection = JDBCTools.getConnection();
System.out.println(connection.getTransactionIsolation());

//mysql隔离模式 的四种隔离模式
// connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
// connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

preparedStatement = connection.prepareStatement(sql);

for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}

resultSet = preparedStatement.executeQuery();

if (resultSet.next()) {
return (E) resultSet.getObject(1);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
JDBCTools.releaseDB(resultSet, preparedStatement, connection);
}
// 2. 取得结果

return null;
}

/**
* Tom 给 Jerry 汇款 500 元.
*
* 关于事务: 1. 如果多个操作, 每个操作使用的是自己的单独的连接, 则无法保证事务. 2. 具体步骤: 1). 事务操作开始前, 开始事务:
* 取消 Connection 的默认提交行为. connection.setAutoCommit(false); 2). 如果事务的操作都成功,
* 则提交事务: connection.commit(); 3). 回滚事务: 若出现异常, 则在 catch 块中回滚事务:
*/
@Test
public void testTransaction() {

Connection connection = null;

try {

connection = JDBCTools.getConnection();
System.out.println(connection.getAutoCommit());

// 开始事务: 取消默认提交.
connection.setAutoCommit(false);

String sql = "UPDATE users SET balance = "
+ "balance - 500 WHERE id = 1";
update(connection, sql);

int i = 10 / 0;
System.out.println(i);

sql = "UPDATE users SET balance = " + "balance + 500 WHERE id = 2";
update(connection, sql);

// 提交事务
connection.commit();
} catch (Exception e) {
e.printStackTrace();

// 回滚事务
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
JDBCTools.releaseDB(null, null, connection);
}

/*
* try {
*
* //开始事务: 取消默认提交. connection.setAutoCommit(false);
*
* //...
*
* //提交事务 connection.commit(); } catch (Exception e) { //...
*
* //回滚事务 try { connection.rollback(); } catch (SQLException e1) {
* e1.printStackTrace(); } } finally{ JDBCTools.releaseDB(null, null,
* connection); }
*/

// DAO dao = new DAO();
//
// String sql = "UPDATE users SET balance = " +
// "balance - 500 WHERE id = 1";
// dao.update(sql);
//
// int i = 10 / 0;
// System.out.println(i);
//
// sql = "UPDATE users SET balance = " +
// "balance + 500 WHERE id = 2";
// dao.update(sql);

}

public void update(Connection connection, String sql, Object... args) {
PreparedStatement preparedStatement = null;

try {
preparedStatement = connection.prepareStatement(sql);

for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}

preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.releaseDB(null, preparedStatement, null);
}
}

}

猜你喜欢

转载自wangyaweinihao.iteye.com/blog/2326267