事务是什么,有什么用?
事务就是一个事情,组成这个事情可能有多个单元,要求这些单元,要么全都成功,要么全都不成功。 在开发中,有事务的存在,可以保证数据完整性。举个简单的例子比如说A向B的账户转账500元A的账户会-500元,B的账户会+500元。要保证这两件事情同时发生,这就是事务 。
事物的特性:ACID
原子性:指的是事物是一个不可分割的工作单位,要么都发生要么都不发生
隔离性:事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离
一致性:事务前后数据的完整性必须保持一致
持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
如果不考虑事务的隔离性,会出现什么问题?
脏读 :脏读是指一个事务读取到了另外一个事务没有提交的数据
事物1:更新一条数据,与此同时事物2:读取事物1更新的数据。
事物1:回滚
导致数据的脏读
不可重复读:A事务查询记录此时B事务更新(update)数据,提交,A事务查询上次记录。俩次查询结果不一致
虚读和幻读: 事务A查询表中所有记录事务B:插入一条记录事务A再次查询表中所有记录。导致不一致
事务隔离级别:
read uncommitted 什么问题也解决不了.
read committed 可以解决脏读,其它解决不了.
Repeatable read 可以解决脏读,可以解决不可重复读,不能解决虚读.
Serializable 它会锁表,可以解决所有问题.
mysql默认隔离级别 repeatable read ,oracle默认隔离级别 read committed
在jdbc中设置事务隔离级别
使用java.sql.Connection接口中提供的方法
void setTransactionIsolation(int level) throws SQLException
参数level可以取以下值:
evel - 以下 Connection 常量之一:
Connection.TRANSACTION_READ_UNCOMMITTED、
Connection.TRANSACTION_READ_COMMITTED、
Connection.TRANSACTION_REPEATABLE_READ
Connection.TRANSACTION_SERIALIZABLE。
(注意,不能使用 Connection.TRANSACTION_NONE,因为它指定了不受支持的事务。)
案例:
银行转账:A用户向B用户汇款500元,当成功汇款之后向用B户发送一天短息。
分析首先A用户转账-500元是事件1.B用户收到+500元是事件2.这两件是都发生的。而接受短信事件3是可以发生的也可以不发生由用户的设置决定。
package driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
public class Demo {
@SuppressWarnings("unused")
public static void main(String[] args) throws SQLException {
// 注册驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/springdemo", "root", "admin");
Savepoint savepoint = null;// 保存点,保存当前操作的位置,之后回滚到指定的位置
try {
// 开启事物
con.setAutoCommit(false);
// 调用dao的in方法 转入资金
// 调用dao的out方法 减去资金
con.setSavepoint();// 设置保存点
// 发送短信
con.commit();// 提交事务
} catch (Exception e) {
if (savepoint != null) {
con.rollback(savepoint);
} else {
con.rollback();
}
//抛出提示
} finally {
if (con != null)
con.close();
}
}
}