JDBC3
一、什么是事务?
事务(Transaction),一般是指要做的或所做的事情。
在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
程序执行单元(unit)—数据库操作的一组SQL语句的执行。
1.由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写
2.由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
例如:我们要实现一个银行转账的操作,首先从A账户减掉指定的金额,然后B账户增加指定的金额,此时转账操作结束。上面的操作如果对应成数据库操作,那么就需要执行两条update语句。数据库把这两条update语句的执行就是一个事务。
指访问并可能更新数据库中各种数据项的一组SQL语句的执行单元(unit)。
二、数据库的事务有4大特征【ACID】
A–原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
C–一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
I–隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
D–持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
三、java中事务的隔离级别
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。
JDBC定义了五种事务隔离级别:
TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读。
TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。
TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。
TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读。
TRANSACTION_NONE JDBC驱动不支持事务
四、JDBC的事务管理操作
JDBC的事务管理操作需要通过java.sql.Connection接口来设置的。
事务的隔离级别
static int TRANSACTION_NONE 指示不支持事务的常量。
static int TRANSACTION_READ_COMMITTED 一个常数表示防止脏读; 可能会发生不可重复的读取和幻像读取。
static int TRANSACTION_READ_UNCOMMITTED 一个常量表示可能会发生脏读,不可重复读和幻读。
static int TRANSACTION_REPEATABLE_READ 一个常量表示防止了脏读和不可重复读; 可以发生幻读。
static int TRANSACTION_SERIALIZABLE 一个常数表示防止脏读,不可重复读和幻影读。
Modifier and Type Constant Field Value
public static final int TRANSACTION_NONE 0
public static final int TRANSACTION_READ_COMMITTED 2
public static final int TRANSACTION_READ_UNCOMMITTED 1
public static final int TRANSACTION_REPEATABLE_READ 4
public static final int TRANSACTION_SERIALIZABLE 8
设置事务隔离级别的方法
void setTransactionIsolation(int level) 尝试将此 Connection对象的事务隔离级别更改为给定的对象。
例如:
Connection接口对象.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Connection接口对象.setTransactionIsolation(8);
设置是否自动提交事务方法【默认JDBC事务是自动提交的】
void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
Connection接口对象.setAutoCommit(falset) ; 设置为手动提交事务。
事务的提交方法
void commit() 使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
事务的回滚方法【异常中执行】
void rollback() 撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁。
例如:
create table t_zhuanzhang(
zz_id int primary key auto_increment,
zz_name varchar(20),
zz_jine int
);
insert into t_zhuanzhang values(null,‘张三’,10000);
insert into t_zhuanzhang values(null,‘李四’,10000);
package com.transactiondemo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//数据库连接类
public class DBConnection {
private static final String NAME = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mybase";
private static final String ZZNAME = "root";
private static final String PASSWORD = "112500";
//加载数据路驱动
static {
try {
Class.forName(NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//得到数据路连接对象
public static Connection getConnection() {
Connection con = null;
try {
con = DriverManager.getConnection(URL, ZZNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
}
package com.zhuanzhang;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.transactiondemo.DBConnection;
public class ZZService {
public void zhuanzhang(String name,int jine,String name2,int jine2) {
Connection con = DBConnection.getConnection();
PreparedStatement ps = null;
try {
//设置手动提交事物
con.setAutoCommit(false);
//设置事物隔离级别
con.setTransactionIsolation(con.TRANSACTION_SERIALIZABLE);
String updatesql = "update t_zhuanzhang set zz_jine = ? where zz_name = ?;";
ps = con.prepareStatement(updatesql);
ps.setInt(1, 10000-jine);
ps.setString(2, name);
int tep = ps.executeUpdate();
if(tep>0) {
System.out.println("减钱成功");
}else {
System.out.println("减钱失败");
}
//手动触发的异常
//int a = 10/0;
ps.setInt(1, 10000+jine2);
ps.setString(2, name2);
int tep2 = ps.executeUpdate();
if(tep2>0) {
System.out.println("加钱成功");
}else {
System.out.println("加钱失败");
}
//提交事物
con.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally {
try {
ps.close();
con.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
package com.test;
import com.zhuanzhang.ZZService;
public class Main {
public static void main(String[] args) {
ZZService ce = new ZZService();
ce.zhuanzhang("张三", 1000, "李四", 1000);
}
}
总结:
1.SQL语句执行的connection与事务设置的connection对象要相同。
2.开始事务conn.setAutoCommit(false);
3.设置事务的隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
4.提交事务conn.commit();
5.设置事务回滚【异常中进行】conn.rollback();
上面我们所操作的事务管理是编码式事务管理,后面我们在学习Spring框架的时候会学习到声明式事务管理。