JDBC-3(Transcation) ****
Posted rttrti
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC-3(Transcation) ****相关的知识,希望对你有一定的参考价值。
3.1 异常的使用说明
- 在工具类中(JDBCUtils)的方法最好声明异常(throws),以便后续实现类中去捕获这些异常。
- 工具类中捕获异常通常没有意义 eg:实现类中connection建立过程出现异常,若工具类中使用try-catch则实现类处理异常后后续仍可继续执行,此时后续执行便无意义。
- 在实现类中去捕获并处理异常,且可使用fially去将开启的资源(connection, preparedStatement, I/O)关闭
3.2 事务简介
3.2.1 事务&事务处理
- 事务:一组逻辑操作单元,使数据从一种状态转变为另一种状态
- 事务处理(事务操作):当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。
3.2.2 JDBC事务处理
- 事务一旦提交就不可回滚
- 当一个连接对象被创建时,默认情况下是自动提交事务
AutoCommit(true)
:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。 - 关闭数据库连接,数据就会自动的提交。 如果多个操作,每个操作使用的是自己单独的连接,则无法保证事务。即同一个事务的多个操作必须在同一个连接下。
- 当一个连接对象被创建时,默认情况下是自动提交事务
JDBC的事务处理:
- 调用Connection对象的setAutoCommit(false)取消自动提交事务
- 所有SQL语句执行成功后调用commit()提交事务
- 出现异常时在catch里调用rollback()回滚事务
- 若此时 Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状态 setAutoCommit(true)。尤其是在使用数据库连接池技术时,执行close()方法前,建议恢复自动提交状态。
点击查看实例
@Test//updateRollBack()实现sql语句执行
public void testUpdate(){
Connection connection = null;
try {
//1.取消数据的自动提交
connection = JDBCUtils.getConnection();
connection.setAutoCommit(false);
String sql1 = "UPDATE account\\n" +
"SET balance = balance - 100\\n" +
"WHERE id = ?;";
String sql2 = "UPDATE account\\n" +
"SET balance = balance + 100\\n" +
"WHERE id = ?;";
updateRollBack(connection, sql1, 1);
//System.out.println(10 / 0);
updateRollBack(connection, sql2, 2);
//2.提交数据
connection.commit();
System.out.println("转账成功!");
} catch (Exception e){
e.printStackTrace();
System.out.println("转账失败!");
try {
//3.出现异常数据回滚
connection.rollback();
} catch (Exception e2){
e2.printStackTrace();
}
} finally {
JDBCUtils.closeResource(connection, null);
}
}
3.2.3 事务的四大属性(ACID)
- 原子性Atomicity: 过程不可分割
- 指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性Consistency: 操作前与操作后总量不变
- 使数据库从一个一致性状态变换到另外一个一致性状态。
- 隔离性Isolation: 多事务操作时,互相不会产生影响
- 指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性Durability: 事务提交后表中数据发生变化
- 一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
3.2.4 数据库的并发问题&隔离级别
1-并发问题
- 脏读:读到了已更新而未提交的数据
- 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的内容就是临时且无效的。
- 不可重复读: 读到了已更新(update)已提交字段
- 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。之后, T1再次读取同一个字段, 值就不同了。
- 幻读: 读到了已插入(insert)已提交字段
- 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。之后, 如果 T1 再次读取同一个表, 就会多出几行。
2-隔离级别
- 一个事务与其他事务隔离的程度称为隔离级别,隔离级别越高,数据一致性越好,但并发性越差。
- READ UNCOMMITTED(读未提交):允许事务读取其他食物未被提交的变更。允许脏读的出现
- READ COMMITTED(读已提交):只允许事务读取已被其他事物提交的变更。不允许脏读,允许可重复读
- REPEATABLE READ(可重复读):确保事务可以多此从一个字段中读取相同的值,事务持续期间禁止任何其他事务对这个字段进行更新。 避免脏读和可重复读
- SERIALIZABLE(串行化):确保事务可以从一个表中读取相同的行,事务持续期间禁止其他事务对该表进行CUD
3-mysql中设置隔离级别
- 查看当前隔离级别:
SELECT @@tx_isolation;
- 设置当前MySQL连接隔离级别:
set transaction isolation level read committed;
- 设置数据库系统的全局隔离级别 :
set global transaction isolation level read committed;
- 补充
- 创建mysql数据库用户:
create user tom identified by \'abc123\';
- 授予权限:
- 授予通过网络方式登录的tom用户,对所有库所有表的全部权限,密码设为root
grant all privileges on *.* to tom@\'%\' identified by \'root\';
- 给tom用户使用本地命令行方式,授予user_db这个库下的所有表的插删改查的权限。
grant select,insert,delete,update on user_db.* to tom@localhost identified by \'abc123\';
- 授予通过网络方式登录的tom用户,对所有库所有表的全部权限,密码设为root
- 创建mysql数据库用户:
4-Java中设置隔离级别
- 设置隔离级别:
connection.setTranscationIsolation(Connection.XXX);
- 获取隔离级别:
connection.getTransactionIsolation();
点击查看隔离级别测试代码
@Test
public void select() throws Exception{
Connection connection = JDBCUtils.getConnection();
//获取当前隔离级别
System.out.println(connection.getTransactionIsolation());
//设置隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
connection.setAutoCommit(false);
String sql = "select * from account;";
List<Account> list = AllSelect.getInstance(connection, Account.class, sql);
for(int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
}
@Test
public void update() throws Exception{
Connection connection = JDBCUtils.getConnection();
String sql = "update account set balance = balance + 100 where id = ?";
connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, 3);
preparedStatement.executeUpdate();
//线程休眠15s
Thread.sleep(15000);
//回滚测试脏读
connection.rollback();
}
以上是关于JDBC-3(Transcation) ****的主要内容,如果未能解决你的问题,请参考以下文章