2016-11-03 11 views
0

當我將結果集中的值放入地圖中時,我在下面代碼的顯示行中得到空指針異常,它有時會工作很多次,但有時它正在拋出NPE,它是一個在後臺運行的服務類型應用程序,每種方法都會打開一個到數據庫的連接並在使用後關閉它。每個方法都有一個同步鎖,以便在連接到數據庫時不會發生衝突。嘗試將查詢結果集放入地圖時引發意外的NPE

public Configuration getConfiguration() { 
    String sql = "SELECT * FROM tbl_settings;"; 
    HashMap<String, String> map = new HashMap<String, String>(); 

    synchronized (_synchObject){ 
    try { 
     open(); 
     PreparedStatement stmt = (PreparedStatement) conn.prepareStatement(sql); 
     ResultSet rs = stmt.executeQuery(); 
     while (rs.next()) { 
      >>line 495: map.put(rs.getString("Field"), rs.getString("Value")); //NPE is thrown in this line: 495 
     } 
    } catch (SQLException e) { 
     logger.error(e); 
    } finally { 
     try { 
      close(); 
     } catch (SQLException e) { 
      logger.error(e); 
     } 
    } 
    return new Configuration(map); 
    } 

方法的open()這裏只是簡單的創建拋出異常的DB-

private void open() throws SQLException { 
    String connectionString = ConfigSettings.getInstance().getDatabaseConnectionString(); 
    conn = (Connection) DriverManager.getConnection(connectionString); 
} 

連接 -

Exception in thread "Thread-2" java.lang.NullPointerException 
at com.mysql.jdbc.ResultSetImpl.buildIndexMapping(ResultSetImpl.java:683) 
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1042) 
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5202) 
at com.twora.entryexit.db.DatabaseAccess.getConfiguration(DatabaseAccess.java:495) 
at com.twora.entryexit.model.Configuration.getInstance(Configuration.java:33) 
at com.twora.entryexit.service.runnables.IntervalledService.runSpecific(IntervalledService.java:33) 
at com.twora.entryexit.service.runnables.RunningService.run(RunningService.java:38) 
at java.lang.Thread.run(Thread.java:745) 

我在每次運行和讀取運行查詢一次結果集之後立即。我該怎麼做才能克服這個問題?

+0

com.twora.entryexit.db.DatabaseAccess.getConfiguration(DatabaseAccess.java:495)從這一行我無法弄清楚方法getConfiguration中的哪一行是495 –

+0

我在行旁邊添加了一條註釋throw NPE(line 495) –

+0

如果這是完整且正確的堆棧跟蹤,則NPE發生在其中一個'getString()'調用中。你可以重寫那段以在'map.put()'前執行'getString()'調用,並將這些值存儲在臨時的'String's中,這樣你就可以看到哪一個失敗了? –

回答

1

您在構建結果集中的三個映射的代碼中遇到異常,該結果集將列名稱和標籤映射到查詢中的索引。這與調用getString無關。

最有可能發生的情況是您的線程同步存在缺陷,並且您有兩個線程同時在同一個結果集對象上工作。發生這種情況是因爲結果集來自連接對象,並且您有兩個線程同時使用來自同一連接的相同結果集對象。

當在結果集中調用「close」時,結果集中的映射將被清除。所以你有一個線程關閉結果集,而另一個線程仍在使用它。這也解釋了爲什麼它在某些時候有效,這一切都取決於時間。

我可以在您的代碼中看到您用於同步的對象不明確。您需要確保您沒有在兩個單獨的線程中同時使用同一個連接對象,並且此時您的同步無法執行此操作。

+0

我沒有從這個方向思考。謝謝,爲了清楚起見,您是否暗示可能存在不在同步聲明內的方法? –

+0

我看到一個正在打開的方法,處理結果集並關閉了不在synchronized語句中的數據庫連接。改變了它,現在正在運行測試。將發佈更新。謝謝@Sean –

+0

我接受了這個答案,因爲它指出我想朝着正確的方向思考,到目前爲止沒有更多的NPE被拋出。 –