Java数据库编程---事务处理

来源:互联网 发布:网络中的涵化理论 编辑:程序博客网 时间:2024/05/21 18:37

事务处理

事务:就是保证操作的一致性,所有的操作要么全部成功,要么全部失败。

事务处理

事务处理在数据库开发中有着非常重要的作用,所谓的事务就是所有的操作要么一起成功,要么一起失败,事务本身具有:原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation)、持久性(Durability)四个特征,以上的四个特征,也被称为ACID特征


原子性

原子性是事务最小的单元,是不可再分割的单元,相当于一个个小的数据库操作,这些操作必须同时完成,如果有一个失败了,则一切的操作将全部失败。例如:A转账和B转账分别是两个不可再分的操作,但是如果A的转账失败,则B的操作也肯定无法成功。


一致性

指的是在数据库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作则系统会维持有效性,如果事务出现了错误,则回到最原始状态,也要维持其有效性,这样保证事务开始时和结束时系统处于一致状态。例如:如果A和B转账成功,则保持其一致性,如果现在A和B的转账失败,则保持操作之前的一致性,即:A的钱不会减少,B的钱不会增加。


隔离性

多个事务可以同时进行且彼此之间无法访问,只有当事务完成最终操作的时候,才可以看见结果。


持久性

当一个系统崩溃时,一个事务依然可以坚持提交,当一个事务完成后,操作的结果保存在磁盘中,永远不会被回滚。例如,所有的资金数都是保存在磁盘中,所以,即使系统发生了错误,用户的资金也不会减少。


如果要想操作事务的话,则必须按照以下的步骤完成:

1、取消掉自动提交:每次执行数据库更新的时候实际上发出SQL命令之后就已经提交上去。

2、开始事务

3、进行一系列的操作

4、如果操作全部合格,则提交事务

5、如果发现有一个地方有问题,则可以进行回滚

6、或者设置一个SAVEPOINT保存事务的提交点。


在正常情况下我们插入一条记录的语句如下:

INSERT INTO user(name,password,age,sex,birthday) VALUES(‘月亮’,'northwind',23,'男',’1990-10-18’);

执行完毕后,结果会立即在数据库中显示:


如果提交之后发现数据是错误的,则此时就没法操作了。因为它是自动提交上去的。


1.现在我们在命令行中输入:


表示关闭自动提交,准备开启事务。


表示启动事务。


我们再次插入一条语句。


这个时候,我们发现数据已经有了。但是,如果我们现在不需要了,我们可以通过rollback命令进行回退。



再次查询数据库,我们发现,刚刚插入的数据已经不存在了。



但是,如果我们再次插入此条数据,并执行commit命令,那么数据将会被永久保存。Rollback命令已经不产生任何作用了。


查询数据库:


我们发现,已经不能再回滚回来了。


在JDBC中同样支持事务的处理操作。

1.不使用事务处理的情况。

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

public class TranDemo01{

    //定义MySQL的数据库驱动程序

    public static final String DBDRIVER = "org.gjt.mm.mysql.Driver";

    //定义MySQL数据库的连接地址

    public static final String DBURL = "jdbc:mysql://localhost:3306/skewrain";

    //MySQL数据库的连接用户名

    public static final String DBUSER = "root";

    //MySQL数据库的连接密码

    public static final String DBPASS = "mysqladmin";

    public static void main(String args[]) throws Exception{

    Connection conn = null;    //数据库连接

    Statement stmt = null;     //定义数据库操作

    Class.forName(DBDRIVER);  //加载驱动程序

    conn = DriverManager.getConnection(DBURL,DBUSER,DBPASS);

    stmt = conn.createStatement();

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

    " VALUES ('skewrain-1','super-1',18,'男','1990-10-18')");

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

    " VALUES ('skewrain-2','super-2',19,'女','1990-10-19')");

    //加入“’”之后,此SQL语句语法就出现了错误,所以,肯定执行到此语句的时候会出现代码错误。

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

    " VALUES ('skewrain-'3','super-3',20,'男','1990-10-20')");

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

    " VALUES ('skewrain-4','super-4',21,'女','1990-10-21')");

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

    " VALUES ('skewrain-5','super-5',22,'男','1990-10-22')");

    int temp[] = stmt.executeBatch();

    System.out.println("更新了:" + temp.length + "条数据。");

    stmt.close();

    conn.close();   

}

};

假如要求插入的五条语句有关联,要么同时成功,要么同时失败。

我们现在编译运行的结果如下:


查询数据库中的结果如下:


我们发现,除了出错的数据没有插入进去,其他的数据插入正常。那么,如果现在这5条记录有相互的关系,则此时这样的实现,是不符合要求的。


JDBC事务操作步骤

在JDBC中,如果要想进行事务处理,也需要按照指定的步骤完成:

1.取消掉Connection中设置的自动提交方式;【conn.setAutoCommit(false);】

2.如果批处理操作成功,则执行提交事务:conn.commit();

3.如果操作失败,则肯定会引发异常,在异常处理中让事务回滚:conn.rollback();

4.如果需要,可以设置Savepoint:Savepoint sp = conn.setSavepoint();。

 

JDBC事务处理的代码如下所示:【TranDemo02.java】

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

public class TranDemo02{

    //定义MySQL的数据库驱动程序

    public static final String DBDRIVER = "org.gjt.mm.mysql.Driver";

    //定义MySQL数据库的连接地址

    public static final String DBURL = "jdbc:mysql://localhost:3306/skewrain";

    //MySQL数据库的连接用户名

    public static final String DBUSER = "root";

    //MySQL数据库的连接密码

    public static final String DBPASS = "mysqladmin";

    public static void main(String args[]) throws Exception{

    Connection conn = null;    //数据库连接

    Statement stmt = null;     //定义数据库操作

    Class.forName(DBDRIVER);  //加载驱动程序

    conn = DriverManager.getConnection(DBURL,DBUSER,DBPASS);

    conn.setAutoCommit(false); //取消掉自动提交

    stmt = conn.createStatement();

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-1','super-1',18,'男','1990-10-18')");

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-2','super-2',19,'女','1990-10-19')");

    //加入“’”之后,此SQL语句语法就出现了错误,所以,肯定执行到此语句的时候会出现代码错误。

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-'3','super-3',20,'男','1990-10-20')");

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-4','super-4',21,'女','1990-10-21')");

    stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-5','super-5',22,'男','1990-10-22')");

    try{

        int temp[] = stmt.executeBatch();

        System.out.println("更新了:" + temp.length + "条数据。");

        conn.commit();  //所有的操作成功了。

    }catch(Exception e){

        try{

             conn.rollback();

        }catch(Exception e1){}

    }

    stmt.close();

    conn.close();   

}

};

我们先将原有的user表删除,再创建一个新的user表。


编译运行程序:


我们查询数据库的内容显示的结果如下:


可见五条插入语句,一条都没有执行。


在开发中,以上的操作过程是标准的事务处理。


正常情况下,可以通过SAVEPOINT保存事务的操作点,因为默认情况下所有的回滚,就是将全部的操作取消掉,而通过Savepoint可以设置回滚的位置。

一个session的操作(每一个连接到数据库上的用户都称为一个session)

操作1

操作2

SAVEPOINT 记录点1

操作3

操作4

Rollback 记录点1

如果回滚的话,回滚到记录点1,操作1和操作2仍保留。


设置Savepoint的类:setSavepoint();


使用SAVEPOINT进行回滚的操作的代码如下:【TranDemo03.java】

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

import java.sql.Savepoint;

public class TranDemo03{

    //定义MySQL的数据库驱动程序

    public static final String DBDRIVER = "org.gjt.mm.mysql.Driver";

    //定义MySQL数据库的连接地址

    public static final String DBURL = "jdbc:mysql://localhost:3306/skewrain";

    //MySQL数据库的连接用户名

    public static final String DBUSER = "root";

    //MySQL数据库的连接密码

    public static final String DBPASS = "mysqladmin";

    public static void main(String args[]) throws Exception{

    Connection conn = null;    //数据库连接

    Statement stmt = null;     //定义数据库操作

    Class.forName(DBDRIVER);  //加载驱动程序

    conn = DriverManager.getConnection(DBURL,DBUSER,DBPASS);

    conn.setAutoCommit(false); //取消掉自动提交

    stmt = conn.createStatement();

    stmt.executeUpdate("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-1','super-1',18,'男','1990-10-18')");

    stmt.executeUpdate("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-2','super-2',19,'女','1990-10-19')");

    Savepoint sp = conn.setSavepoint(); //设置保存点

    stmt.executeUpdate("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-4','super-4',21,'女','1990-10-21')");

    stmt.executeUpdate("INSERT INTO user(name,password,age,sex,birthday)" +

        " VALUES ('skewrain-5','super-5',22,'男','1990-10-22')");

    try{

        conn.rollback(sp); //回滚到保存点

        conn.commit();  //所有的操作成功了。

    }catch(Exception e){

    }

    stmt.close();

    conn.close();   

}

};

由于事务处理的隔离性,我们需要删除user表重新建立。

编译运行的结果如下所示:


查看数据库的内容如下所示:


我们发现只有回滚点前的插入语句有效。


小结:

JDBC操作事务的步骤:

1.取消掉自动提交;

2.执行多条SQL语句;

3.如果没有异常,则提交事务;

4.否则则进行事务的回滚操作。

0 0
原创粉丝点击