1,什么是事务
事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败。 如:网上转账就是典型的要用事务来处理,用以保证数据的一致性。
2,事务和锁
当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其它用户改表表的结构.这里对我们用户来讲是非常重要的。
3, 提交事务
当执使用commit语句可以提交事务.当执行了commit语句子后,会确认事务的变化、结束事务、删除保存点、释放锁,当使用commit语句结束事务子后,其它会话将可以查看到事务变化后的新数据
4,在pl/sql中简单的事务保存
1) 设置保存点
savepoint 保存点名
2) 取消部分事务
rollback to 保存点名
3) 取消全部事务
rollback
程序演示:
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
777 huge
7369 zhangtao CLERK 7902 1980/12/17 800.00 20
7499 ALLEN SALESMAN 7698 1981/2/20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981/2/22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981/4/2 2975.00 20
7654 MARTIN SALESMAN 7698 1981/9/28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981/5/1 2850.00 30
7782 CLARK MANAGER 7839 1981/6/9 2450.00 10
7788 SCOTT ANALYST 7566 1987/4/19 3000.00 20
7839 KING PRESIDENT 1981/11/17 5000.00 10
7844 TURNER SALESMAN 7698 1981/9/8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987/5/23 1100.00 20
7900 JAMES CLERK 7698 1981/12/3 950.00 30
7902 FORD ANALYST 7566 1981/12/3 3000.00 20
7934 MILLER CLERK 7782 1982/1/23 1300.00 10
15 rows selected
SQL> savepoint aaa;//设置保存点
Savepoint created
SQL> delete from emp where empno=777;//删除其中的某一行
1 row deleted
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 zhangtao CLERK 7902 1980/12/17 800.00 20
7499 ALLEN SALESMAN 7698 1981/2/20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981/2/22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981/4/2 2975.00 20
7654 MARTIN SALESMAN 7698 1981/9/28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981/5/1 2850.00 30
7782 CLARK MANAGER 7839 1981/6/9 2450.00 10
7788 SCOTT ANALYST 7566 1987/4/19 3000.00 20
7839 KING PRESIDENT 1981/11/17 5000.00 10
7844 TURNER SALESMAN 7698 1981/9/8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987/5/23 1100.00 20
7900 JAMES CLERK 7698 1981/12/3 950.00 30
7902 FORD ANALYST 7566 1981/12/3 3000.00 20
7934 MILLER CLERK 7782 1982/1/23 1300.00 10
14 rows selected
SQL> rollback to aaa;//回到之前的保存点
Rollback complete
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
777 huge
7369 zhangtao CLERK 7902 1980/12/17 800.00 20
7499 ALLEN SALESMAN 7698 1981/2/20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981/2/22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981/4/2 2975.00 20
7654 MARTIN SALESMAN 7698 1981/9/28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981/5/1 2850.00 30
7782 CLARK MANAGER 7839 1981/6/9 2450.00 10
7788 SCOTT ANALYST 7566 1987/4/19 3000.00 20
7839 KING PRESIDENT 1981/11/17 5000.00 10
7844 TURNER SALESMAN 7698 1981/9/8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987/5/23 1100.00 20
7900 JAMES CLERK 7698 1981/12/3 950.00 30
7902 FORD ANALYST 7566 1981/12/3 3000.00 20
7934 MILLER CLERK 7782 1982/1/23 1300.00 10
15 rows selected
注意:用完之后的保存点将消失,要是使用须重新设置保存点
5,在java中如何实现呢?
1):将自动提交关闭 (oracle默认的是自动提交事物)
Connection里面的 setAutoCommit(false) 设为false
2):写dml语句
3):抓异常
4):在异常里面回滚事物
Connection rollback();
程序演示如下:
程序1:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class jdbcText {
public static void main(String args[]){
HelpJdbc hj=HelpJdbc.getInstance();
Connection conn=null;
try {
conn=hj.getconn();
conn.setAutoCommit(false);
PreparedStatement ps=conn.prepareStatement("update emp set sal=sal-1000 where ename='KING'");
ps.executeUpdate();
// int a=5/0;
PreparedStatement ps2=conn.prepareStatement("update emp set sal=sal+1000 where ename='SMITH'");
ps2.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
// hj.exeDml("insert into emp(empno,ename) values(777,'huge')");
hj.closeRes();
}
}
程序2:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//这里采用了单例设计模式 私有的构造方法,静态的对象,公开的静态的getInstance方法
public class HelpJdbc {
private Connection c=null;
private PreparedStatement ps=null;
private ResultSet rs;
public static HelpJdbc hj=null;
public static HelpJdbc getInstance(){
if(hj==null){
hj=new HelpJdbc();
}
return hj;
}
private HelpJdbc(){
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
throw new RuntimeException();
}
}
public Connection getconn(){
try {
return c=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","ztoracle");
} catch (SQLException e) {
throw new RuntimeException();
}
}
public int exeDml(String sql){
try {
c=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","ztoracle");
ps=c.prepareStatement(sql);
return ps.executeUpdate(sql);
} catch (SQLException e) {
throw new RuntimeException();
}
}
public ResultSet querry(String sql){
ResultSet rs=null;
try {
c=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","ztoracle");
ps=c.prepareStatement(sql);
rs=ps.executeQuery();
} catch (SQLException e) {
throw new RuntimeException();
}
return rs;
}
public void closeRes(){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
rs=null;
throw new RuntimeException();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
ps=null;
throw new RuntimeException();
}
}
if(c!=null){
try {
c.close();
} catch (SQLException e) {
c=null;
throw new RuntimeException();
}
}
}
}