2015-07-11 27 views
1

這可能看起來像一個重複的問題,但事實並非如此。我試圖尋找超過48小時的答案,沒有結果。什麼是SQLite JDBC連接的準確語法?

首先,正在關閉PreparedStatment & ResultSet在SQLite JDBC連接中是必需的嗎?因爲我無法這樣做。

try { 
     Class.forName(database.getJDBC_DRIVER()); 
     cnn = DriverManager.getConnection(database.getDB_URL()); 
     p = cnn.prepareStatement(query); 
     rs = p.executeQuery(); 
     p.close(); 
     cnn.close(); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      System.out.println(p.isClosed()); 
      if (cnn != null) cnn.close(); 
      System.out.println(p.isClosed()); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 

正如你所看到的,我在try塊中關閉了PreparedStatement。但是,當我在try塊之外檢查其狀態時,結果始終爲false。 (這意味着它沒有關閉)。

此外,如果我在finally塊中有下面的代碼,它會拋出一個錯誤,指出連接已關閉。我對做什麼感到困惑。我應該保持原樣嗎?我的代碼不會泄漏嗎?

} finally { 
    try { 
     if (p != null) p.close(); *// It errors out here...* 
     if (cnn != null) cnn.close(); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
} 

下面是堆棧跟蹤 -

java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (Connection is closed) 
    at org.sqlite.core.DB.newSQLException(DB.java:890) 
    at org.sqlite.core.CoreStatement.internalClose(CoreStatement.java:109) 
    at org.sqlite.jdbc3.JDBC3Statement.close(JDBC3Statement.java:35) 
    at tg.cat.DropDown.getData(DropDown.java:28) 
    at tg.loginscreen.LoginScreenLayout.<init>(LoginScreenLayout.java:22) 
    at tg.cat.CatMain.getScene(CatMain.java:27) 
    at tg.cat.CatMain.start(CatMain.java:18) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl$$Lambda$53/855499929.run(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl$$Lambda$45/186276003.run(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl.lambda$null$170(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl$$Lambda$48/1635925971.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl$$Lambda$47/237061348.run(Unknown Source) 
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source) 
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
+0

'finally'做了什麼? –

+0

在finally塊中,我試圖再次關閉連接。以防萬一,由於任何錯誤,連接不會首先嚐試。同時,我也和PreparedStatment一樣,但它錯誤地說 - 連接已關閉。 –

+0

這似乎不是一個關於SQLite的問題,而是關於Java SE JDBC API的問題。提供您正在獲取的錯誤的堆棧跟蹤會很有幫助。此外,Oracle Java語言網站上的JDBC教程將涵蓋您希望瞭解的所有資料:http://docs.oracle.com/javase/tutorial/jdbc/ – scottb

回答

3

finally塊不管異常是否被拋出或不執行。因此,您不需要使用它來關閉連接再次,而是將其用作關閉連接的唯一位置。其次,注意關閉連接將變量不會重置爲null

try { 
    Class.forName(database.getJDBC_DRIVER()); 
    cnn = DriverManager.getConnection(database.getDB_URL()); 
    p = cnn.prepareStatement(query); 
    rs = p.executeQuery(); 
} catch (SQLException e) { 
    e.printStackTrace(); 
} catch (ClassNotFoundException e) { 
    e.printStackTrace(); 
} finally { 
    try { 
     if (rs != null) { 
      rs.close(); 
     } 
     if (p != null) { 
      p.close(); 
     } 
     if (cnn != null) { 
      cnn.close(); 
     } 
    } catch (SQLException e) { 
     System.err.println("Can't close an object, not much I can do"); 
    } 
} 
1

Mureinik是正確的,但即使是最好使用try-with-resources功能,讓你甚至不必擔心關閉任何東西(手動)首先。

try (Connection cnn = DriverManager.getConnection(database.getDB_URL()); 
    PreparedStatement p = cnn.prepareStatement(query)) { 
    // prepare your statement 
    try (ResultSet rs = p.executeQuery()) { 
    // process result set 
    } 
} catch (SQLException e) { 
    throw new RuntimeException("Unexpected SQLException", e); 
}