1.事务
在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元。
程序执行单元------数据库操作的一组SQL语句的执行。
(1)由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写
(2)由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
例如:我们要实现一个银行转账的操作,首先从A账户减掉指定的金额,然后B账户增加指定的金额,此时转账操作结束。上面的操作如果对应成数据库操作,那么就需要执行两条update语句。数据库把这两条update语句的执行就是一个事务。
事务--指访问并可能更新数据库中各种数据项的一组SQL语句的执行单元(unit)。
2.事务的四大特征【ACID】
A---原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
C--一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
I--隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
D--持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
3.事务的隔离级别
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。
JDBC定义了五种事务隔离级别:
TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读。
TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。
TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。
TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读。
TRANSACTION_NONE JDBC驱动不支持事务
Modifier and Type | Constant Field | Value |
public static final int | 0 | |
public static final int | 2 | |
public static final int | 1 | |
public static final int | 4 | |
public static final int | 8 |
设置事务隔离级别的方法【可以直接写整数,也可以用connection.级别】
void setTransactionIsolation(int level) 尝试将此 Connection对象的事务隔离级别更改为给定的对象。
例如:
Connection接口对象.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Connection接口对象.setTransactionIsolation(8);
4. 事务管理操作
(1)JDBC的事务管理操作需要通过java.sql.Connection接口来设置。
(2)设置事务隔离级别
(3)设置是否自动提交事务方法【默认JDBC事务是自动提交的】
void setAutoCommit(Boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
例:Connection接口对象.setAutoCommit(false); 设置为手动提交事务
(4)事务提交方法
Connection接口对象.commit;
commit() 使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
(5)事务回滚方法【异常中执行】
rollback() 撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁
异常中执行回滚操作,如有异常,事务将会重新回到事务最开始重新执行,比如步骤1和步骤2,步骤1执行完成后,执行步骤2,步骤2有异常,会进入到try…catch里面的回滚操作,然后回到步骤1 前面,又从步骤1 开始。
注意:回滚操作必须之前有手动设置提交的方法,如果是默认的自动提交,则回滚无效。
代码演示:【银行转账例子】
import java.sql.Connection;
import java.sql.DriverManager;
public class DBconnection {
private static final String DRIVERNAME="com.mysql.jdbc.Driver";
private static final String URL="jdbc:mysql://127.0.0.1:3306/test";
private static final String USER="root";
private static final String PASSWORD="123456";
static{
try{
Class.forName(DRIVERNAME);
}catch(Exception e){
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn=null;
try{
conn=DriverManager.getConnection(URL, USER, PASSWORD);
}catch(Exception e){
e.printStackTrace();
}
return conn;
}
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class ZhangHuDao {
public static void zhuanzhang(String name1,String name2,double money){
Connection conn=null;
PreparedStatement prepareStatement =null;
try{
conn=DBconnection.getConnection();
//设置手动提交
conn.setAutoCommit(false);
//设置事务隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
String sql="update t_zhanghu set zhanghu_money=? where zhanghu_name=?;";
prepareStatement = conn.prepareStatement(sql);
prepareStatement.setDouble(1, 10000-money);
prepareStatement.setString(2,name1 );
prepareStatement.executeUpdate();
//
prepareStatement.setDouble(1, 10000+money);
prepareStatement.setString(2, name2);
prepareStatement.executeUpdate();
//提交事务
conn.commit();
prepareStatement.close();
conn.close();
}catch(Exception e){
//回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
import java.sql.Connection;
public class Main {
public static void main(String[] args) {
ZhangHuDao.zhuanzhang("zhangsan", "lisi", 5000);
}
}
总结:
- SQL语句执行的connection与事务设置的connection对象要相同。
- 开始事务conn.setAutoCommit(false);
- 设置事务的隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
- 提交事务conn.commit();
- 设置事务回滚【异常中进行】conn.rollback();
上面我们所操作的事务管理是编码式事务管理,后面我们在学习Spring框架的时候会学习到声明式事务管理。