处理事物
标签(空格分隔): jdbc
数据库事物
事物是一组逻辑操作单元,将数据从一种状态切换到另一种状态
其具有ACID的特点:
- 原子性:要么都执行,要么都回滚
- 一致性:保证数据的状态操作前和操作后保持一致
- 隔离性:多个事物操作同一相同数据库的同一个数据时,一个事物的执行不受另一个事物的干扰
- 持久性:一个事物一旦提交,则数据将持久化到本地,除非其他事物对其进行修改
JDBC处理事物
关于事物:如果多个操作,每个操作使用的是自己的单独的连接,则无法保证事物。
具体步骤:
1. 事物操作开始前,开始事物:取消Connection的默认提交行为connection.setAutoCommit(false);
2. 如果事物的操作都成功,则提交事物connection.commit();
3. 若出现异常,则在catch块中回滚事物connection.rollback();
代码如下:
/**
* Tom给Jerry汇款500
*/
@Test
public void testTransaction() {
Connection connection = null;
try {
connection = JDBCTools.getConnection();
//1. 开始事物:取消默认提交
connection.setAutoCommit(false);
//2. 开始操作
String sql = "UPDATE users SET balance = balance - 500 WHERE id = 1";
upadte(connection,sql);
//设置异常
int i = 10/0;
System.out.println(i);
sql = "UPDATE users SET balance = balance + 500 WHERE id = 2";
upadte(connection,sql);
//3. 提交事物
connection.commit();
} catch (Exception e) {
e.printStackTrace();
//4. 回滚事物
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
JDBCTools.release(null,null,connection);
}
}
/**
* 与DAO中不同的方法,最主要的区别是Connection是通过参数传递进来的
* @param connection
* @param sql
* @param args
*/
public void upadte(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 (SQLException e) {
e.printStackTrace();
} finally {
JDBCTools.release(null,preparedStatement,null);
}
}
隔离级别
并发问题
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:
脏读: 一个事物读取到了另一个事物未提交的数据
不可重复读: 同一个事物中,多次度渠道的数据不一致
幻读: 一个事物读取数据时,另外一个事物进行更新,导致第一个事物读取到了没有更新的数据
隔离性与隔离级别
数据库事务的隔离性:
数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响, 避免各种并发问题。
一个事务与其他事务隔离的程度称为隔离级别。 数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度, 隔离级别越高,数据一致性就越好,但并发性越弱。
四种隔离级别:
- READ UNCOMMITTED:读未提交
- READ COMMITTED:读已提交,可以避免脏读
- REPEATABLE READ:可重复度,可以避免脏读,不可重复读和一部分幻读(Mysql默认的隔离级别)
- SERIALIZABLE:可以避免脏读,不可重复读和幻读
测试事物的隔离级别
在JDBC程序中可以通过Connection的setTransactionIsolation来设置事物的隔离级别:
//就是在创建connection后,设置事物的隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);