2017-07-07 97 views
1

我沒有太多的Java經驗,並希望如果你提出這個問題。捕捉Java SQLExceptions

我有下面的代碼段(方法)以建立與PostgreSQL數據庫的JDBC連接:

public void establishDBConnection() throws SQLException { 

    try (Connection connection = DriverManager.getConnection(
       "jdbc:postgresql://" + dbServer + ":" + dbPort + "/" + 
       dbDatabase, dbUser, dbPassword)) 
    catch (SQLException e) { 
     logger.error("Connection to Postgres Database Failed: " + 
     e.printStackTrace(); 
    } 
} 

我期望的SQLException將由catch塊一旦被捕獲作爲該方法可以」 t建立與數據庫的連接(服務器關閉)。 catch塊在控制檯上放置異常,但是我看到在執行getConnection方法之後的相同異常顯示在前面。因此,我在控制檯上有兩個相同的例外。見下文。

問題是,這是什麼原因以及如何強制應用程序顯示由catch塊生成的異常。

日誌:

Jul 07, 2017 9:11:53 PM org.postgresql.Driver connect 
SEVERE: Connection error: 
**org.postgresql.util.PSQLException: Connection to localhost:5433 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.** 
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:265) 
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) 
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:194) 
    at org.postgresql.Driver.makeConnection(Driver.java:431) 
    at org.postgresql.Driver.connect(Driver.java:247) 
    at java.sql.DriverManager.getConnection(DriverManager.java:664) 
    at java.sql.DriverManager.getConnection(DriverManager.java:247) 
    at excel2db.service.impl.DBConnectionPostgresImpl.establishDBConnection(DBConnectionPostgresImpl.java:38) 
    at excel2db.excel2db.main(excel2db.java:86) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 
Caused by: java.net.ConnectException: Connection refused: connect 
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) 
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) 
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) 
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) 
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) 
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) 
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) 
    at java.net.Socket.connect(Socket.java:589) 
    at org.postgresql.core.PGStream.<init>(PGStream.java:62) 
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) 
    ... 13 more 

21:11:53.465 [main] ERROR e.s.impl.DBConnectionPostgresImpl - **Connection to Postgres Database Failed: Connection to localhost:5433 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.** 
+1

應用服務器可能啓用其他日誌記錄。 – OldProgrammer

+5

有一個例外的層次結構。第二個是根本原因。控制檯是正確的。 JVM在您預期的位置打印完整的堆棧跟蹤。 – duffymo

+0

您不必爲代碼添加任何供應商特定的例外。這就是整個問題。您不應該因爲更改數據庫供應商而重新編寫應用程序。 – duffymo

回答

3

,只有一個例外,被印在你的例子:SQLException中被抓。您認爲第二個例外是(僅作爲文本顯示)原因 SQLException:Postgres拋出一個SQLException,它本身被拋出,因爲Portgres嘗試連接時存在網絡ConnectException。

當您需要診斷故障時,這種例外情況非常方便。它允許回到原來的低級別問題的來源。就像例如,知道你沒有收到你的郵件(NoMailException)是有用的,因爲郵局正在罷工(OnStrikeException),因爲政府決定降低工資(WagesTooLowException)。如果您剛剛收到了原始NoMailException,您將無法知道您沒有收到郵件的原因,知道這可能是暫時的,等等。

在這種特殊情況下,您可以推斷出無法連接到服務器,而不是例如,密碼不正確。

鏈接異常僅僅是通過調用另一個異常作爲參數的異常構造函數來實現的(大多數例外都是這樣做的)。請參閱https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html#Exception-java.lang.String-java.lang.Throwable-

+0

感謝您的詳細回覆!根據我以上閱讀的內容,這是可以預期的,並且沒有必要改變代碼中的內容。可能期望消除「e.printStackTrace();」由於根本原因無論如何都被Postgres發現,所以這是不需要的。因此,一般案例中的catch塊應該記錄(描述)高層次的問題。請讓我知道如果這是不正確的。 – Andrey

+0

代碼是完全沒用的:它會立即打開連接並關閉它。如果它做了一些有用的事情(比方說,在數據庫中插入一行),那麼它可能根本就不會捕獲異常。相反,它應該讓它傳播以指示調用者該行無法正確插入。或者它應該捕獲它,然後拋出另一個更高級別的異常,並鏈接最初的SQLException:'throw InsertFailedException(e);' –

+0

正確的,實際上我刪除了一部分代碼,只專注於異常。再次感謝您的意見。 – Andrey

0

您需要將驅動程序的類加載到內存中。試試這個代碼:

嘗試{

Class.forName("org.postgresql.Driver"); 

Connection connection = DriverManager.getConnection(jdbc:postgresql://server_address:5432/database_name?user=usernam&password=password); 

}趕上(例外的例外){

exception.printStackTrace(); 

}