¿Cómo limitar el número de filas devueltas de Oracle en el nivel de origen de datos JDBC?

StackOverflow https://stackoverflow.com/questions/320299

  •  11-07-2019
  •  | 
  •  

Pregunta

¿Hay alguna forma de limitar las filas devueltas en el nivel de origen de datos de Oracle en una aplicación Tomcat?

Parece que maxRows solo está disponible si lo configura en la fuente de datos en el código Java. Poner maxRows="2" en la fuente de datos no se aplica.

¿Hay alguna otra forma de limitar las filas devueltas? ¿Sin un cambio de código?

¿Fue útil?

Solución

No es algo que esté disponible en el nivel de configuración. Es posible que desee verificar que haga lo que quiere que haga de todos modos: vea el javadoc para setMaxRows . Con Oracle, aún recuperará cada fila para la consulta y luego simplemente eliminará las que están fuera del rango. Realmente necesitaría usar rownum para que funcione bien con Oracle y tampoco puede hacerlo en la configuración.

Otros consejos

La pregunta es por qué desea limitar el número de filas devueltas. Podría haber muchas razones para hacer esto. El primero sería limitar los datos devueltos por la base de datos. En mi opinión, esto no tiene sentido en la mayoría de los casos, ya que si quisiera obtener ciertos datos solo entonces usaría una declaración diferente o agregaría una condición de filtro o algo así. P.ej. si usa rownum de Oracle, no sabe exactamente qué datos están en las filas que obtiene y qué datos no están incluidos, ya que simplemente le dice a la base de datos que desea la fila x a y.
El segundo enfoque es limitar el uso de memoria y aumentar el rendimiento para que el ResultSet que obtenga del controlador JDBC no incluya todos los datos. Puede limitar el número de filas retenidas por ResultSet usando Statement.setFetchSize () . Si mueve el cursor en ResultSet más allá del número de filas recuperadas, el controlador JDBC obtendrá los datos faltantes de la base de datos. (En el caso de Oracle, la base de datos almacenará los datos en un cursor de referencia al que accede directamente el controlador JDBC).

  

* Cuidado: el siguiente código se proporciona como ejemplo puro. No tiene   probado * Por lo tanto, puede dañarse a usted mismo o a su computadora o incluso golpearlo   en la cara.

Si quiere evitar modificar sus consultas SQL pero aún quiere tener un código limpio (lo que significa que su código puede mantenerse), puede diseñar la solución usando envoltorios. Es decir, mediante el uso de un pequeño conjunto de clases que envuelven las existentes, puede lograr lo que desea sin problemas para el resto de la aplicación, que seguirá pensando que funciona con DataSource, Connection y Statement reales.

1: implemente una clase StatementWrapper o PreparedStatementWrapper, según lo que su aplicación ya utilice. Esas clases son envoltorios alrededor de instancias normales de Statement o PreparedStatement. Se implementan simplemente usando la instrucción interna como delegado que hace todo el trabajo, excepto cuando se trata de una instrucción QUERY (método Statement.executeQuery ()). Solo en esa situación precisa, el contenedor rodea la consulta con las dos cadenas siguientes: & Quot; SELECT * FROM (& Quot; y & Quot;) WHERE ROWNUM & Lt; " + maxRowLimit. Para el código básico del contenedor de código, vea cómo se ve el DataSourceWrapper a continuación.

2: escriba un contenedor más: ConnectionWrapper que envuelve una conexión que devuelve StatementWrapper en createStatement () y PreparedStatementWrapper en prepareStatement (). Esas son las clases previamente codificadas que toman delegateConnection.createStatement () / prepareStatement () de ConnectionWrapper como argumentos de construcción.

3: repita el paso con un DataSourceWrapper. Aquí hay un ejemplo de código simple.

public class DataSourceWrapper implements DataSource
{
    private DataSource mDelegate;

    public DataSourceWrapper( DataSource delegate )
    {
        if( delegate == null ) { throw new NullPointerException( "Delegate cannot be null" );
        mDelegate = delegate;
    }

    public Connection getConnection(String username, String password)
    {
        return new ConnectionWrapper( mDelegate.getConnection( username, password ) );
    }

    public Connection getConnection()
    {
        ... <same as getConnection(String, String)> ...
    }
}

4 - Finalmente, use ese DataSourceWrapper como el DataSource de su aplicación. Si está utilizando JNDI (NamingContext), este cambio debería ser trivial.

La codificación de todo esto es rápida y muy sencilla, especialmente si está utilizando IDE inteligente como Eclipse o IntelliJ que implementará los métodos de delegación automáticamente.

Si sabe que solo tratará con una tabla, defina una vista con rownum en la instrucción where para limitar el número de filas. De esta forma, el número de filas se controla en la base de datos y no necesita especificarse como parte de ninguna consulta desde una aplicación cliente. Si desea cambiar el número de filas devueltas, redefina la vista antes de ejecutar la consulta.

Un método más dinámico sería desarrollar un procedimiento y pasar varias filas, y hacer que el procedimiento devuelva un ref_cursor a su cliente. Esto tendría la ventaja de evitar el análisis duro en la base de datos y aumentar el rendimiento.

Ok, un cambio de código tendrá que ser entonces.

El escenario limita una herramienta de informes ad hoc para que el usuario final no retire demasiados registros y genere un informe que no se puede utilizar.

Ya utilizamos la gestión de recursos basada en el costo de Oracle.

Eche un vistazo a esta página con una descripción de limitar cuánto se absorbe en la aplicación Java a la vez. Como señala otra publicación, la base de datos aún extraerá todos los datos, esto es más para controlar el uso de la red y la memoria en el lado de Java.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top