• 数据库事物操作


    事务

    什么是事务?
    转账:
    1. 给wc账户减1000元
    2. 给wcxf账户加1000元

    当给wc账户减1000元后,抛出了异常!这会怎么样呢?我相信从此之后,wc再也不敢转账了。

    使用事务就可以处理这一问题:把多个对数据库的操作绑定成一个事务,要么都成功,要么都失败!

    ---------------------------------------------------------------------------------------------------------------------------------------------

    事物的特性:ACID

    * 原子性事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
    * 一致性事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
    * 隔离性隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
    * 持久性一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

    ---------------------------------------------------------------------------------------------------------------------------------------------

    MySQL操作事务

    1. 开始事务:start transaction
    2. 结束事务:commit//提交事物rollback//事物回滚

    (1)事物回滚

    (2)事物提交

    ---------------------------------------------------------------------------------------------------------------------------------------------

    JDBC事务

    1. 开始事务con.setAutoCommit(false);
    2. 结束事务con.commit()con.rollback();

    public class Jdbc2 {
        public static void main(String[] args) {
            Connection con=null;
            PreparedStatement pst=null;
            try {
                con = JDBCUtils.getConnection();
                 //开启事物
                con.setAutoCommit(false);//开启手动事物
                pst=con.prepareStatement("UPDATE  acction SET mun=mun-100 WHERE username=? ");
                pst.setString(1, "zhangsan");
                pst.executeUpdate();
                //人为创建异常
                int index=1/0;
                pst=con.prepareStatement("UPDATE  acction SET mun=mun+100 WHERE username=? ");
                pst.setString(1, "wangwu");
                pst.executeUpdate();
                con.commit();//提交事物
                
            } catch (Exception e) {
                try {
                    con.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }finally{
                //关闭
                JDBCUtils.createClose(null, pst, con);
            }
        }
    }

    ---------------------------------------------------------------------------------------------------------------------------------------------

    保存点

    保存点的是可以回滚到事务中的某个位置,而不是回滚整个事务。
    回滚到保存点不会结束事务。
    设置保存点:Savepoint sp = con.setSavepoint();
    回滚到保存点:con.rollback(sp);

    public class Jdbc1 {
          public static void main(String[] args) {
              Connection con=null;
              PreparedStatement pst=null;
              Savepoint sp=null;
              try{
                 con = JDBCUtils.getConnection();
                 con.setAutoCommit(false);//手动开启事物
                 sp=con.setSavepoint();
                 pst=con.prepareStatement("INSERT INTO acction(username,mun) VALUES(?,?)");
                 for(int i=1;i<=2000;i++){
                     if(i==1002){
                         int index=i/0;
                     }
                     pst.setString(1, "lxp");
                     pst.setInt(2, i);
                     pst.executeUpdate();
                     if(i%1000==0){
                        sp=con.setSavepoint();
                     } 
                 }
                 con.commit();//事物提交
              }catch(Exception e){
                  try {
                    con.rollback(sp);
                    con.commit();
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }//回滚事物
                  e.printStackTrace();
              }finally{
                  JDBCUtils.createClose(null, pst, con) ;
              }
        }
    

    ---------------------------------------------------------------------------------------------------------------------------------------------

    事务隔离级别

    * 脏读:读到未提交


    * 不可重复读:两次读取不一致,读取到另一事务修改的记录


    * 幻读:两次读取不一致,读取到另一事务插入的记录

    ---------------------------------------------------------------------------------------------------------------------------------------------

    四大隔离级别
    * SERIALIZABLE(串行化):对同一数据的访问是串行的,即非并发的,所以不会出现任何并发问题。易出现死锁,效率太低!不可用!
    * REPEATABLE READ(可重复读):防止了脏读、不可重复读,但没有防止幻读
    * READ COMMITTED(读已提交):防止了脏读,但没有防止不可重复读,以及幻读
    * READ UNCOMMITTED(读未提交):可能出现所有并发问题,效率最高,但不可用!

    MySQL默认事务隔离级别为:REPEATABLE READ
    Oracle默认事务隔离级别为:READ COMMITTED

    -------------------------------------------------------------------------------------------------------------------------------------------------

    MySQL设置事务隔离级别

    /* 查看:*/select @@tx_isolation
    /* 设置:*/set transaction isolation level 四选一

    JDBC设置事务隔离级别

    con.setTransactionIsolation(四选一)

    ------------------------------------------------------------------------------------------------------------------------------------------------------

    代码JDBCUtils代码:

    需要配置dbconfig.properties文件

    public class JDBCUtils {
        static Properties props = null;
        //绑定线程
        static private ThreadLocal<Connection> t1=new ThreadLocal<Connection>();
        static {
            // 加载本地配置文件
            try {
                InputStream in = JDBCUtils.class
                        .getResourceAsStream("dbconfig.properties");
                props = new Properties();
                props.load(in);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 加载驱动
            try {
                Class.forName(props.getProperty("driverClassName"));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        /**
         * 获得Connection连接
         * @return
         * @throws Exception
         */
        public static Connection getConnection() throws Exception {
            Connection conn = t1.get();
            if(conn==null){
            // 加载配合
             conn= DriverManager.getConnection(props.getProperty("url"),
                    props.getProperty("username"), props.getProperty("password"));
            t1.set(conn);
            }
            return conn;
        }
       /**
        * 关闭所有连接
        * @param rs
        * @param statement
        * @param conn
        */
        public static void createClose(ResultSet rs, PreparedStatement statement,
                Connection conn) {
            try {
                if (rs != null)
                    rs.close();
                if (rs != null)
                    statement.close();
                if (rs != null)   
                    conn.close();
        if(t1!=null){
                    t1.remove();
                } }
    catch (Exception e) { e.printStackTrace(); } } }
  • 相关阅读:
    转:什么是即时编译(JIT)!?OpenJDK HotSpot VM剖析
    用好spring mvc validator可以简化代码
    接口服务中的日志
    rest api参数与content-type
    【单页应用】全局控制器app应该干些什么?
    【webapp的优化整理】要做移动前端优化的朋友进来看看吧
    【单页应用】理解MVC
    【单页应用】view与model相关梳理
    【单页应用之通信机制】view之间应该如何通信
    【单页应用巨坑之History】细数History带给单页应用的噩梦
  • 原文地址:https://www.cnblogs.com/lxp503238/p/6639178.html
Copyright © 2020-2023  润新知