← 返回首页
JDBC教程(九)
发表时间:2020-03-23 13:18:06
讲解JDBC之事务

在JDBC中处理事务,都是通过Connection完成的。JDBC中一个Connection对象被创建时,默认是auto-commit模式,也就是一个sql Statement作为一个事务,执行完成后自动commit。如果支持多个Statement组成一个事务,则要禁止auto-commit模式,也就是非自动提交事务。

1.JDBC如何使用事务

Connection的四个方法与事务有关:

实例:使用事务插入一条记录之后抛出RuntimeException,并实现回滚。

public class TransactionDemo {

    public static void main(String[] args) {

        String sql = "insert into students (sname,gender) values (?,?)";
        Connection conn = null;
        PreparedStatement pstmt = null;
        try{
            conn = DBUtils.getConnection();
            pstmt = conn.prepareStatement(sql);
            //开启事务
            conn.setAutoCommit(false);
            //设置事务的隔离级别
            //注意:通常不推荐修改数据库默认的事务隔离级别,这里仅仅是做个测试。
            conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
            pstmt.setString(1,"刘备");
            pstmt.setString(2,"男");
            pstmt.executeUpdate();

            //这里抛出一个RuntimeException;
            System.out.println(100/0);
         }catch(Exception ex){
            ex.printStackTrace();
            try {
                //回滚
                conn.rollback();
            }catch(SQLException e){
                e.printStackTrace();
            }
        }finally{
            try {
                //提交事务
                conn.commit();
                conn.setAutoCommit(true);
            }catch(SQLException e){
                e.printStackTrace();
            }
        }

    }
}

2.设置保存点


class Students {
    private String sname;
    private String gender;

    public Students() {
    }

    public Students(String sname, String gender) {
        this.sname = sname;
        this.gender = gender;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Students{" +
                "sname='" + sname + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

public class TransactionDemo {

    public static List<Students> studentsList = new ArrayList<Students>();

    public static void initStudentsList() {
        for (int i = 1; i <= 10; i++) {
            Students s = new Students("张" + i, "男");
            studentsList.add(s);
        }
    }

    public static void main(String[] args) {

        initStudentsList();
        String sql = "insert into students (sname,gender) values (?,?)";

        Connection conn = null;
        PreparedStatement pstmt = null;
        Savepoint savepoint=null;

        try{
            conn = DBUtils.getConnection();
            pstmt = conn.prepareStatement(sql);
            //开启事务
            conn.setAutoCommit(false);
            //设置事务的隔离级别
            conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
            for(Students s : studentsList) {
                pstmt.setString(1, s.getSname());
                pstmt.setString(2,s.getGender());
                pstmt.addBatch();
            }
            //执行批处理
            pstmt.executeBatch();
            savepoint = conn.setSavepoint("保存点1");
            //这里抛出一个MysqlDataTruncationException;‘未知性别’超出了gender字段的长度。
            sql = "update students set gender = '未知性别' where sid = 5";
            pstmt.addBatch(sql);
            pstmt.executeBatch();


         }catch(Exception ex){
            ex.printStackTrace();
            try {
                //回滚到保存点
                conn.rollback(savepoint);
            }catch(SQLException e){
                e.printStackTrace();
            }
        }finally{
            try {
                //提交事务
                conn.commit();
                conn.setAutoCommit(true);
            }catch(SQLException e){
                e.printStackTrace();
            }
        }

    }
}

运行后,我们发现尽管在执行更新语句(update)时抛出了一个MysqlDataTruncation异常。但是并不影响前十条插入语句执行成功,说明成功回滚到了保存点位置。