2010-01-19 16 views
6

Estoy confundido sobre el comportamiento de un ResultSet que es del tipo TYPE_SCROLL_SENSITIVE.Comportamiento de ResultSet.TYPE_SCROLL_SENSITIVE

Mi comprensión de esto es -
1.) Ejecuto una consulta de selección que me devuelve un conjunto de resultados. Imprimo el valor de una columna en particular en la primera fila.
2.) Luego ejecuto Thread.sleep (10000), que detiene el programa durante 10 segundos.
3.) Mientras el programa está inactivo, manualmente realizo una actualización a la misma columna en el DB (a través del indicador de SQL).
4.) Después de 10 segundos, vuelvo a imprimir el valor de la misma columna en la primera fila del conjunto de resultados.

En el paso 4, espero que el valor de la columna impresa sea diferente del valor impreso en el paso 1. Pero siempre obtengo el mismo valor (incluso si mi ResultSet es del tipo SCROLL_TYPE_SENSITIVE).

¿Estoy entendiendo mal algo aquí?

A continuación se muestra el código que uso.

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")); 
} 

¡Gracias por su ayuda con anticipación!

+0

Además, acabo de notar que JDBC proporciona otro método "ResultSet.refreshRow () ". Agregar esto al código (justo antes del paso 4) me da el resultado deseado. ¿Para qué sirve TYPE_SCROLL_SENSITIVE? –

+0

refreshRow() simplemente significa disparar una consulta al DB para obtener el estado más reciente. –

Respuesta

11

¿Estoy entendiendo mal algo aquí?

Sí. Debe buscar de nuevo para obtener el último estado de la tabla, ya sea mediante el encendido de un SELECT usted mismo, o llamando al ResultSet.refreshRow(). Además, lea los documentos de ResultSet.refreshRow() antes de usarlo, de lo contrario, podría obtener resultados inesperados.

Los estados doc respecto TYPE_SCROLL_SENSITIVE,

TYPE_SCROLL_SENSITIVE

La constante que indica el tipo de un objeto de ResultSet que es desplazable y generalmente sensible a los cambios realizadas por otros.

Lo que significa simplemente que sería sensible a los cambios realizados por otros en el mismo objeto ResultSet. Para entender el concepto, aconsejo mirar este oficial JDBC Tutorial: Updating Tables.

bien, la edición de mi post para incluir la línea específica del tutorial original,

Con un conjunto de resultados desplazable, se puede traslado a filas que desea cambiar, y si el tipo es TYPE_SCROLL_SENSITIVE, puede obtener el nuevo valor en una fila después de haberlo cambiado.

+0

Todavía no entiendo :(. "Usted puede obtener el nuevo valor en una fila después de que lo haya cambiado". ¿Quiere decir esto que si ejecuto ResultSet.updateXXX (columnIndex, val), puedo conseguir el valor actualizado ejecutando ResultSet.getXXX (columnIndex)? –

+0

Sí, exactamente. Ese no es el caso con el otro, 'TYPE_SCROLL_INSENSITIVE' –

+0

No funciona para mí :( –

4

Creo que está utilizando mysql como su db, y este es un error conocido.

Permítanme desarrollar por integración global

De acuerdo con la documentación de Oracle en el sitio de Java se utiliza para TYPE_SCROLL_SENSITIVE 2 purposes-

controlador 1.Mysql ahora puede mover el puntero del JDBC del conjunto de resultados de aquí para allá (que de lo contrario, simplemente avanza), básicamente se activa el desplazamiento {por lo que ahora puede hacer resultset.previous() y el puntero volverá}

2.Para mostrar los valores actualizados (los cambios internos), realizados a la base de datos.

Usted está atrapado en el segundo punto ...

Ver su programa no está funcionando, porque nunca se utilizó el concepto de de fetchSize();

siempre utilizando JDBC, el conductor obtiene un número predeterminado de filas en la caché que se muestra (por ejemplo: cargas Oracle 10 filas por defecto)

por lo TYPE_SCROLL_SENSITIVE mostrará el valor actualizado de la siguiente recarga sólo caché . es como si tuviera 100 filas en la base de datos, actualizó todas, pero hasta entonces solo se obtuvieron 10 filas, por lo que obtendrá las otras 90 filas actualizadas impresas posteriormente, ya que el controlador cargará estas tablas en 9 rondas de administración de la memoria caché .

para definir explícitamente el número de filas que se deben buscar (por ejemplo, cambiar el número de filas de 10 a 1 para el oráculo) puede definir explícitamente el fetchSize() al crear la instrucción. (Pero utilizando la memoria caché ineficazmente, final ralentiza la velocidad)

por lo mientras se iniciaba la declaración como:

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

añadir una línea como:

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

crear conjuntoResultados como:

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

para verificar los datos: setFetchSize impresión de conjunto resultado, si se pasa de declaración a conjuntoResultados mientras SYSOUT que la configuración de ir a buscar se ha guardado, como:

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

si el sysout da '1' como tamaño de búsqueda, verá sus actualizaciones dinámicas desde el programa como está, , pero si da '0' eso significa que su base de datos no admite la inicialización dinámica de fetchSize();

Este es el problema con mysql, mysql recupera de manera predeterminada todas las filas en ResultSet y, por lo tanto, la actualización interna dinámica no recupera los valores dinámicos. (la actualización interna es la actualización realizada por otro hilo del mismo programa).

Aquí está el error apoyar mi punto de errores de 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(); 
     } 
    }