2010-01-19 79 views
6

Tôi nhầm lẫn về hành vi của một ResultSet thuộc loại TYPE_SCROLL_SENSITIVE.Hành vi của ResultSet.TYPE_SCROLL_SENSITIVE

Hiểu biết của tôi về điều này là -
1.) Tôi thực hiện truy vấn chọn trả về cho tôi tập hợp kết quả. Tôi in ra giá trị của một cột cụ thể trong hàng đầu tiên.
2.) Sau đó, tôi thực hiện Thread.sleep (10000), tạm dừng chương trình trong 10 giây.
3.) Trong khi chương trình đang ngủ, tôi tự cập nhật cho cùng một cột trong DB (thông qua lời nhắc SQL).
4.) Sau 10 giây, tôi lại in giá trị của cùng một cột trong hàng đầu tiên của tập kết quả.

Ở bước 4, tôi mong đợi giá trị cột in khác với giá trị được in ở bước 1. Nhưng tôi luôn nhận được cùng một giá trị (ngay cả khi ResultSet của tôi thuộc loại SCROLL_TYPE_SENSITIVE).

Tôi có hiểu sai điều gì đó ở đây không?

Dưới đây là mã tôi sử dụng.

private void doStuff() throws Exception 
{ 
    final String query = "select * from suppliers where sup_id=420"; 

    Statement stmt = this.con.createStatement(
     ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); 

    ResultSet rs = stmt.executeQuery(query); 

    rs.next(); 

    System.out.println("City : " + rs.getString("city")); 

    Thread.sleep(10000); // While this executes, I do a manual update ! 

    System.out.println("City : " + rs.getString("city")); 
} 

Cảm ơn sự giúp đỡ của bạn trước!

+0

Ngoài ra, tôi chỉ nhận thấy rằng JDBC cung cấp một phương pháp "ResultSet.refreshRow () ". Việc thêm mã này vào mã (ngay trước bước 4) cho tôi kết quả mong muốn. Sử dụng TYPE_SCROLL_SENSITIVE là gì? –

+0

refreshRow() chỉ đơn giản là có nghĩa là kích hoạt truy vấn tới DB để có trạng thái mới nhất. –

Trả lời

11

Tôi có hiểu nhầm điều gì đó ở đây không?

Có. Bạn phải tìm nạp lại lần nữa để có trạng thái mới nhất của bảng, bằng cách tự mình bật lên một số SELECT hoặc gọi số ResultSet.refreshRow(). Hơn nữa, đọc các tài liệu của ResultSet.refreshRow() trước khi sử dụng nó, nếu không bạn có thể nhận được kết quả bất ngờ.

Các tiểu bang doc về TYPE_SCROLL_SENSITIVE,

TYPE_SCROLL_SENSITIVE

Hằng chỉ ra kiểu cho một đối tượng ResultSet đó là cuộn và thường nhạy cảm với những thay đổi làm bởi những người khác.

Chỉ đơn thuần có nghĩa là nó sẽ nhạy cảm với những thay đổi của những người khác trong cùng một đối tượng ResultSet. Để hiểu khái niệm này, tôi sẽ khuyên bạn nên xem chính thức này JDBC Tutorial: Updating Tables.

Được rồi, chỉnh sửa bài của tôi để bao gồm các dòng cụ thể từ các hướng dẫn ban đầu,

Với một tập kết quả cuộn, bạn có thể chuyển sang hàng bạn muốn thay đổi, và nếu gõ là TYPE_SCROLL_SENSITIVE, bạn có thể nhận được giá trị mới trong một hàng sau khi bạn đã thay đổi nó.

+0

Tôi vẫn không hiểu: (. "bạn có thể nhận được giá trị mới liên tiếp sau khi bạn đã thay đổi nó". Điều này có nghĩa là nếu tôi thực thi ResultSet.updateXXX (columnIndex, val), tôi có thể nhận được Giá trị cập nhật bằng cách thực thi ResultSet.getXXX (columnIndex)? –

+0

Vâng, chính xác, đó không phải là trường hợp khác, 'TYPE_SCROLL_INSENSITIVE'. –

+0

Không hoạt động cho tôi: ( –

4

Tôi nghĩ bạn đang sử dụng mysql làm db của mình và đây là lỗi đã biết.

Hãy để tôi xây dựng fully-

Theo Oracle tài liệu trên trang web java TYPE_SCROLL_SENSITIVE được sử dụng cho 2 purposes-

1.Mysql driver bây giờ đã có thể di chuyển con trỏ kết quả bộ jdbc để và fro (mà nếu không chỉ đi theo hướng về phía trước), vì vậy về cơ bản cuộn được kích hoạt {vì vậy bây giờ bạn có thể làm resultset.previous() và con trỏ sẽ quay lại}

2.Để hiển thị các giá trị cập nhật (các thay đổi nội bộ), được thực hiện vào cơ sở dữ liệu.

Bạn đang mắc kẹt ở điểm thứ 2 ...

Xem chương trình của bạn không hoạt động vì bạn chưa bao giờ sử dụng khái niệm fetchSize();

bất cứ khi nào sử dụng JDBC, người lái xe lấy một số mặc định của hàng vào bộ nhớ cache sẽ được hiển thị (cho ví dụ: tải oracle 10 dòng theo mặc định)

nên TYPE_SCROLL_SENSITIVE sẽ hiển thị giá trị cập nhật của tải lại bộ nhớ cache tiếp theo chỉ . nó giống như bạn có 100 hàng trong DB, bạn cập nhật tất cả, nhưng cho đến khi chỉ có 10 hàng được tải xuống, vì vậy bạn sẽ nhận được 90 hàng khác được cập nhật sau đó, vì trình điều khiển sẽ tải các bảng này trong 9 vòng quản lý bộ đệm .

để xác định rõ số hàng cần tìm nạp (ví dụ: thay đổi số hàng từ 10 đến 1 cho oracle), bạn có thể xác định rõ fetchSize() trong khi tạo câu lệnh (nhưng sử dụng bộ nhớ cache không hiệu quả, tại cuối chậm tốc độ)

như vậy trong khi khởi tuyên bố như sau:

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, 
      ResultSet.CONCUR_UPDATABLE); 

thêm một dòng như:

stmt.setFetchSize(1); //1 is the no. of rows that will be fetched. 

tạo ResultSet như:

ResultSet rset = stmt.executeQuery("select * from persons"); 

để xác minh dữ liệu: in setFetchSize từ ResultSet, nếu nó đi từ tuyên bố ResultSet trong khi Sysout so với cấu hình quyến rũ đã được lưu, như:

System.out.println("fetch size: " + resultSet.getFetchSize()); 

nếu sysout cho '1' như kích thước tìm nạp, bạn sẽ thấy các cập nhật động của mình từ chương trình vì nó là, nhưng nếu nó cho '0' có nghĩa là DB của bạn không hỗ trợ khởi tạo động fetchSize();

Đây là vấn đề với mysql, mặc định mysql tìm nạp tất cả số hàng vào ResultSet và do đó cập nhật nội bộ động, không tìm nạp giá trị động. (cập nhật nội bộ là bản cập nhật được thực hiện bởi một số chủ đề khác của cùng một chương trình).

Đây là lỗi hỗ trợ quan điểm của tôi về lỗi sql:

sql bugs fetchSize Bug

if you use oracle,this java doc copied from oracle documentation will just work fine: 

orcale docs TYPE_SCROLL_SENSITIVE example ResultSet5.java

import java.sql.*; 

public class ResultSet5 
{ 
    public static void main(String[] args) throws SQLException 
    { 
    // Load the Oracle JDBC driver 
    DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); 
    // Connect to the database 
    // You can put a database name after the @ sign in the connection URL. 
    Connection conn = 
    DriverManager.getConnection ("jdbc:oracle:oci8:@", "scott", "tiger"); 
    // Create a Statement 
    Statement stmt = conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, 
            ResultSet.CONCUR_UPDATABLE); 
    // Set the statement fetch size to 1 
    stmt.setFetchSize (1); 
    // Query the EMP table 
    ResultSet rset = stmt.executeQuery ("select EMPNO, ENAME, SAL from EMP"); 
    // List the result set's type, concurrency type, ..., etc 
    showProperty (rset); 


// List the query result 
System.out.println ("List ENO, ENAME and SAL from the EMP table: "); 
while (rset.next()) 
{ 
    System.out.println (rset.getInt(1)+" "+rset.getString(2)+" "+ 
         rset.getInt(3)); 
} 
System.out.println(); 

// Do some changes outside the result set 
doSomeChanges (conn); 

// Place the cursor right before the first row 
rset.beforeFirst(); 

// List the employee information again 
System.out.println ("List ENO, ENAME and SAL again: "); 
while (rset.next()) 
{ 
    // We expect to see the changes made in "doSomeChanges()" 
    System.out.println (rset.getInt(1)+" "+rset.getString(2)+" "+ 
         rset.getInt(3)); 
} 

// Close the RseultSet 
rset.close(); 

// Close the Statement 
stmt.close(); 

// Cleanup 
cleanup(conn); 

// Close the connection 
conn.close(); 
    } 

    /** 
    * Update the EMP table. 
    */ 
    public static void doSomeChanges (Connection conn)throws SQLException 
    { 
    System.out.println ("Update the employee salary outside the result set\n"); 

    Statement otherStmt = conn.createStatement(); 
    otherStmt.execute ("update emp set sal = sal + 500"); 
    otherStmt.execute ("commit"); 
    otherStmt.close(); 
    } 

    /** 
    * Show the result set properties like type, concurrency type, fetch 
    * size,..., etc. 
    */ 
    public static void showProperty (ResultSet rset) throws SQLException 
    { 
    // Verify the result set type 
switch (rset.getType()) 
{ 
    case ResultSet.TYPE_FORWARD_ONLY: 
    System.out.println ("Result set type: TYPE_FORWARD_ONLY"); 
    break; 
    case ResultSet.TYPE_SCROLL_INSENSITIVE: 
    System.out.println ("Result set type: TYPE_SCROLL_INSENSITIVE"); 
    break; 
    case ResultSet.TYPE_SCROLL_SENSITIVE: 
    System.out.println ("Result set type: TYPE_SCROLL_SENSITIVE"); 
    break; 
    default: 
    System.out.println ("Invalid type"); 
    break; 
} 

// Verify the result set concurrency 
switch (rset.getConcurrency()) 
{ 
    case ResultSet.CONCUR_UPDATABLE: 
    System.out.println 
       ("Result set concurrency: ResultSet.CONCUR_UPDATABLE"); 
    break; 
    case ResultSet.CONCUR_READ_ONLY: 
    System.out.println 
       ("Result set concurrency: ResultSet.CONCUR_READ_ONLY"); 
    break; 
    default: 
    System.out.println ("Invalid type"); 
    break; 
} 
// Verify the fetch size 
System.out.println ("fetch size: "+rset.getFetchSize()); 
System.out.println(); 
    } 

    /* Generic cleanup.*/ 
     public static void cleanup (Connection conn) throws SQLException 
     { 
     Statement stmt = conn.createStatement(); 
     stmt.execute ("UPDATE EMP SET SAL = SAL - 500"); 
     stmt.execute ("COMMIT"); 
     stmt.close(); 
     } 
    }