zoukankan      html  css  js  c++  java
  • JDBC的事务操作

    事务概念

    对多个SQL指令进行操作,只有这些指令都成功时,才能认为整个操作是完成的,这样的操作称为”事务操作“。如果一个SQL指令操作失败,之前的各个操作都要取消,这种取消动作称为”回滚 (rollback)“。

    JDBC中的事务操作是基于同一个数据连接的,各个连接之间相互独立。当数据连接断开后,一个事务就结束了。事务操作的方法都位于java.sql.Connection接口中。

    JDBC事务操作默认是自动提交的,一条对数据库的更新表达式代表一项事务操作,操作成功后,系统会自动调用commit()来提交,否则会调用rollback()来回滚。如果想取消自动提交可以调用setAutoCommit(false),回复自动提交则可以设置其实参为true。取消自动提交可以灵活地将多个表达式作为一个事务,然后使用commit()来提交,如果出现异常可以使用rollback()来回滚。


    实例

    import java.sql.*;
    
    public class Main {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Connection con = null;
            Statement smt;
            
            try{
                Class.forName("com.mysql.jdbc.Driver");//加载JDBC MYSQL驱动
                con=DriverManager.getConnection("jdbc:mysql://localhost:3306/javatemp","root","root"); //建立数据库连接
                con.setAutoCommit(false);//取消事务的自动提交
                //System.out.println(con.getTransactionIsolation()); //获取事务默认加锁方式
                //con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//设置事务加锁方式
                //System.out.println(con.getTransactionIsolation());//获取事务当前加锁方式
                smt=con.createStatement();//创建Statement对象
                smt.executeUpdate("insert into users(username) values('beston5')");//执行SQL命令
                con.rollback();//回滚
                smt.executeUpdate("insert into users(username) values('beston6')");
                con.commit();//提交
                con.setAutoCommit(true);//恢复事务的自动提交            
                PreparedStatement ps=con.prepareStatement("insert into users(username) values(?)");//使用prepareStatement对象操作数据指令
                ps.setString(1,"oseye6");//设置占位符值
                ps.executeUpdate();    //执行SQL命令
    
                ResultSet res=smt.executeQuery("select * from users");//执行SQL命令并获得结果集
                while(res.next()){//处理结果集
                    System.out.println("userid:"+res.getInt("userid")+"\t"+"username:"+res.getString("username"));                
                }
                res.close();//关闭结果集连接的数据并释放JDBC资源
                
            }catch(Exception ex){
                ex.printStackTrace();//打印异常信息        
            }finally{
                if(con!=null){
                    try{
                        con.close();//关闭数据库连接
                    }catch(Exception ex){                    
                        ex.printStackTrace();
                    }
                }
                
            }
        }
    }
    View Code

    上面注释的应该很详细了,"beston5"不会插入到数据库,"beston6"和"oseye6"将会插入到数据中。


    JDBC 对数据库的加锁机制

    先来看三个概念:

    • 脏数据读写(dirty reads):当一个事务修改了某一数据行的值而未提交时,另一事务读取了此行值。倘若前一事务发生了回滚,则后一事务将得到一个无效的值(脏数据)。
    • 重复读写(repeatable reads):当一个事务在读取某一数据行时,另一事务同时在修改此数据行。则前一事务在重复读取此行时将得到一个不一致的值。
    • 影象读写(phantomreads):当一个事务在某一表中进行数据查询时,另一事务恰好插入了满足了查询条件的数据行。则前一事务在重复读取满足条件的值时,将得到一个额外的“影象“值。

    JDBC API支持事务对数据库的加锁,并且提供了5种操作支持:

    static int TRANSACTION_NONE= 0; //禁止事务操作和加锁。
    static  int TRANSACTION_READ_UNCOMMITTED= 1; //允许脏数据读写、重复读写和影象读写
    static  int TRANSACTION_READ_COMMITTED= 2;//禁止脏数据读写,允许重复读写和影象读写
    static  int TRANSACTION_REPEATABLE_READ= 4;//禁止脏数据读写和重复读写,允许影象读写
    static  int TRANSACTION_SERIALIZABLE= 8;//禁止脏数据读写、重复读写和允许影象读写

    上述归类可以分为两种加锁密度,表加锁和行加锁。其中最后一项为表加锁,其余3~4项为行加锁。

    如上代码中,取消

    //System.out.println(con.getTransactionIsolation()); //获取事务默认加锁方式
    //con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//设置事务加锁方式
    //System.out.println(con.getTransactionIsolation());//获取事务当前加锁方式

    的注释,将会看到默认枷锁是为4,设置后的枷锁为2.


    总结:

    随着加锁方式值增加,其事务的独立性增加,更能有效的防止事务操作之间的冲突;同时也增加了加锁的开销,降低了用户之间访问数据库的并发性,程序的运行效率也回随之降低。因此得平衡程序运行效率和数据一致性之间的冲突。

    一般来说:

    • 对于只涉及到数据库的查询操作时,可以采用TRANSACTION_READ_UNCOMMITTED方式;
    • 对于数据查询远多于更新的操作,可以采用TRANSACTION_READ_COMMITTED方式;
    • 对于更新操作较多的,可以采用TRANSACTION_REPEATABLE_READ;
    • 在数据一致性要求更高的场合再考虑最后一项,由于涉及到表加锁,因此会对程序运行效率产生较大的影响;

    另外,在oracle中数据库驱动对事务处理的缺省值是TRANSACTION_NONE,即不支持事务操作,所以需要在程序中手动进行设置;而MYSQL是不支持TRANSACTION_NONE的,这点需要注意。

    出处:http://www.zhaiqianfeng.com    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    解释器
    桥接
    组合
    hbase读性能优化
    Hbase为什么写比读快
    http和https区别
    R apply() 函数和 tapply() 函数
    R 语言 decostand() 函数
    R多行交叉作图
    k-mean 拐点
  • 原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4617049.html
Copyright © 2011-2022 走看看