2012-12-15 64 views
0

好的,我有一段被稱爲幾次的代碼。但是在一些測試中,我注意到我的ResultSet根據數據庫返回錯誤。經過進一步調查,我發現它以某種方式被重用。值得一提的是,當我重新啓動程序時,它會取得正確的結果。 SQL總是一樣的。ResultSet被重用

我的代碼:

PreparedStatement ps = connection.prepareStatement(sql); 
ps.setInt(1, packet.getUserId()); 
ResultSet dbResult = ps.executeQuery(); 

while(dbResult.next()) 
{ 
    System.out.println("There were items!"); 
    Item item = new Item(); 
    item.setItemType(dbResult.getInt(1)); 
    item.setFromUser(dbResult.getString(2)); 
    item.setItemMessage(dbResult.getString(3)); 
    toReturn.add(item); 
} 

這一直是我的測試序列:

  • 獲得從ResultSet中的行一次,並得到正確的結果 - OK
  • 從表中特定刪除所有行上面的sql使用,這意味着ResultSet下次應該什麼都不會返回。
  • 嘗試再次獲取(現在它應該返回0行),但它返回與步驟1中完全相同的行,即使數據庫表爲空。

應該關閉ResultSet或使用後的某些東西,或者我錯過了什麼? 即使數據庫中沒有任何內容,我也會從ResultSet中獲得結果。我可以保證SQL是合法的,但ResultSet似乎不會在第二次調用時創建它。

EDIT(連接初始化代碼)

public class DBFactory 
{ 
    protected String databaseName = null; 
    protected String username = null; 
    protected String password = null; 
    protected Connection connection = null; 
    protected Statement statement = null; 

    protected DBFactory(String databaseName, String username, String password) 
    { 
     this.databaseName = databaseName; 
     this.username = username; 
     this.password = password; 
    } 

    protected void initConnection() 
    { 
     if (databaseName == null || username == null || password == null) 
      throw new IllegalStateException(); 

     try 
     { 
      Class.forName("com.mysql.jdbc.Driver").newInstance(); 
      this.connection = DriverManager.getConnection(this.databaseName, this.username, this.password); 
      this.statement = this.connection.createStatement(); 
     } 
     catch (Exception e) 
     { 
      System.out.println("DBFactory " + e.getMessage()); 
     } 
    } 
+1

您已經忽略了代碼中的重要部分,顯示瞭如何刪除行並重新發出查詢以及連接上的選項(REPEATABLE_READ等)。沒有這些細節,我們只是猜測。 –

+0

我不會從代碼中刪除它們,我會在程序外手動執行該操作。 –

+0

發佈創建連接的代碼。 – reprogrammer

回答

1

我希望你有自動提交關閉了連接。

據我瞭解你的問題,這個小代碼的例子將證明它。

package org.yi.happy.mysql; 

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 

public class RepeatQuery { 
    public static void main(String[] args) throws Exception { 
     Class.forName("com.mysql.jdbc.Driver").newInstance(); 

     setupDatabase(); 

     System.out.println("opening database..."); 
     Connection connection = openConnection(); 
     connection.setAutoCommit(false); 

     queryDatabase(connection); 

     deleteRecords(); 

     queryDatabase(connection); 

     connection.close(); 
    } 

    private static Connection openConnection() throws SQLException { 
     return DriverManager.getConnection("jdbc:mysql://localhost/test", null, 
       null); 
    } 

    private static void setupDatabase() throws SQLException { 
     Connection conn = openConnection(); 

     System.out.println("doing insert on another connection..."); 
     PreparedStatement stmt = conn 
       .prepareStatement("insert into strings(id, value) values(?, ?)"); 

     stmt.setInt(1, 1); 
     stmt.setString(2, "test"); 
     stmt.execute(); 

     stmt.setInt(1, 2); 
     stmt.setString(2, "data"); 
     stmt.execute(); 

     stmt.close(); 
     conn.close(); 
    } 

    private static void deleteRecords() throws SQLException { 
     Connection conn = openConnection(); 
     System.out.println("doing delete on another connection..."); 
     PreparedStatement stmt = conn.prepareStatement("delete from strings"); 
     stmt.execute(); 

     stmt.close(); 
     conn.close(); 
    } 

    private static void queryDatabase(Connection connection) 
      throws SQLException { 
     System.out.println("doing query..."); 
     PreparedStatement ps = connection 
       .prepareStatement("select id, value from strings"); 
     ResultSet dbResult = ps.executeQuery(); 

     while (dbResult.next()) { 
      int id = dbResult.getInt(1); 
      String value = dbResult.getString(2); 
      System.out.println(id + " <=> " + value); 
     } 
    } 
} 

的上述輸出是

doing insert on another connection... 
opening database... 
doing query... 
2 <=> data 
1 <=> test 
doing delete on another connection... 
doing query... 
2 <=> data 
1 <=> test 

如果更改

  connection.setAutoCommit(false); 

讀取

  connection.setAutoCommit(true); 

輸出變爲

doing insert on another connection... 
opening database... 
doing query... 
2 <=> data 
1 <=> test 
doing delete on another connection... 
doing query... 

這是你所期望的。

+0

我做了connection.setAutoCommit和那工作:)謝謝 –

0

您很可能在一個事務中,如果您提交或回滾當前事務,您將看到數據庫的當前狀態。

嘗試

 connection.rollback(); 

 connection.commit(); 

查詢之前,或者打開自動提交。