1. 程式人生 > >JDBC異常處理和資源釋放問題

JDBC異常處理和資源釋放問題

之前我們在介紹JDBC載入註冊驅動的時候說過有三種方式,是哪三種方式呢?我們再來看看

Class.forName("com.mysql.jdbc.Driver");
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");

以上三種方式都可以實現JDBC的驅動載入註冊,這裡我們推薦使用Class.forName(“com.mysql.jdbc.Driver”);另外DriverManager.registerDriver(new com.mysql.jdbc.Driver());其實可以直接寫成new com.mysql.jdbc.Driver();這裡我們瞭解就好,大可不必深究,除非有必要!

今天我們來說說JDBC連線資料庫的異常的正確處理,還記得之前我們是怎麼處理的嗎?沒錯,我們直接給丟擲了,程式碼是這個樣子滴!


@Test
      public void ddlAndExceptionTest() throws Exception{


            String sql = "CREATE TABLE `t_student` (`id` bigint(10)  DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;";

            //載入註冊驅動
            Class.forName("com.mysql.jdbc.Driver"
); //獲取連線物件 Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "123456"); //建立獲取語句物件 Statement st = connection.createStatement(); //執行SQL語句 st.executeUpdate(sql); //釋放資源 st.close(); connection.close(); }

我們這裡直接throws Exception了,其實這樣是不妥的,那正確的異常處理方式是什麼呢?在此之前我們應該知道處理異常我們都用try catch的,有時候也配合finally一起使用,在處理JDBC連線資料庫的異常時我們需要著重瞭解的還有資源釋放的問題,就是那個xxx.close,下面我們一步步結合程式碼來說

首先我們看需要處理異常的程式碼

這裡寫圖片描述

諸如此類的程式碼異常我們都將它使用try catch包裹


 //載入註冊驅動
            try {
                  Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }

然後將catch中的異常型別改為Exception,然後繼續寫程式碼,完成JDBC連線資料庫的後續步驟,程式碼如

 try {
                  //載入註冊驅動
                  Class.forName("com.mysql.jdbc.Driver");
                  //獲取連線物件
                  Connection connection =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root","123456");
                  //建立或者獲取語句物件
                  Statement statement = connection.createStatement();
                  //執行sql語句
                  statement.executeUpdate(sql);
                  //釋放資源
                  statement.close();
                  connection.close();

            } catch (Exception e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }

到這裡我們就已經將異常做了相應的處理,但是這裡面還有個很大的問題那就是資源釋放的問題,也就是說目前釋放資源的程式碼放在那裡是不妥的,如果之前程式碼出現個什麼意外,那麼資源就無法釋放了,可能有人說了,為什麼這個資源必須要釋放呢?

那麼我們就來說道說道這個資源為什麼必須釋放呢?
我們先來看這個Connection,這傢伙是資料庫的連線物件,你可要知道在JDBC中Connection這個資源是非常稀有的,使用之後必須馬上釋放,我記得在哪看過關於這塊釋放資源的一個原則好像是“晚點用,早點放”,嗯,大概就是這個意思,總之在使用的過程中只有用到的時候才去建立這個物件,使用之後也要記得立馬釋放。

因此,為了保證資源的必須釋放,我們該怎麼做呢?沒錯,我們可以將釋放資源的程式碼放到finally裡,這樣就可以保證無論之前的程式碼怎樣,釋放資源的程式碼必定執行。

這樣程式碼就變成了現在這個樣子了


 @Test
      public void testException(){
            String sql = "CREATE TABLE `t_one` (`id` bigint(10) DEFAULT  NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
            Statement statement = null;
            Connection connection = null;
            try {
                  //載入註冊驅動
                  Class.forName("com.mysql.jdbc.Driver");
                  //獲取連線物件
                  connection =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root","123456");
                  //建立或者獲取語句物件
                  statement = connection.createStatement();
                  //執行sql語句
                  statement.executeUpdate(sql);
                  //釋放資源
                  statement.close();
                  connection.close();

            } catch (Exception e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            } finally {
                  //釋放資源
                  try {
                        statement.close();
                        connection.close();
                  } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                  }

            }


      }

到了這一步,你看看是不是就可以了呢?其實不然,這裡面還是不行,哪裡不行呢?我們來看,假如在connection沒有來得及賦值的時候出現了意外,這樣就會直接執行finally裡面的程式碼,這樣就會導致一個空物件呼叫close,就會引起新的異常導致程式崩潰,對於statement依然如此,因此,我們需要進行判空!

因此finally裡面釋放資源的程式碼應該這樣寫


finally {
                  //釋放資源
                  if (statement!=null) {
                        try {
                              statement.close();
                        } catch (SQLException e) {

                              e.printStackTrace();
                        }finally {
                              if (connection!=null) {
                                    try {
                                          connection.close();
                                    } catch (SQLException e) {

                                          e.printStackTrace();
                                    }
                              }
                        }
                  }

            }

因此正確完整的程式碼如下


 //正確處理JDBC的異常
      @Test
      public void testHandleException(){

            Connection con = null;
            Statement st = null;
            String sql = "CREATE TABLE `t_new1` (`id` bigint(10) DEFAULT  NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;";

            //異常標準程式碼格式結構
            try{

                  //這裡存放可能出現異常的程式碼
                  //載入註冊驅動
                  Class.forName("com.mysql.jdbc.Driver");
                  //獲取連線物件
                  con =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root","123456");
                  //獲取連線語句
                  st = con.createStatement();
                  //執行sql語句
                  st.executeUpdate(sql);

            }
            catch (Exception e) {

                  e.printStackTrace();
            }finally {
                  //釋放資源、
                  if (st!=null) {
                        try {
                              st.close();
                        } catch (Exception e2) {
                              // TODO: handle exception
                        }finally {
                              if (con!=null) {
                                    try {
                                          con.close();
                                    } catch (Exception e3) {
                                          // TODO: handle exception
                                    }
                              }
                        }
                  }
            }     
      }

歡迎關注微信公眾號:一個自學的程式設計師