Pregunta

Me dan una tarea de convertir una gran mesa en el archivo XML personalizado. Me va a utilizar Java para este trabajo.

Si simplemente emitir un "SELECT * FROM cliente", puede devolver enorme cantidad de datos que eventualmente causando OOM. Me pregunto, ¿hay una manera que puede procesar el registro de inmediato una vez que estén disponibles, y eliminar el registro de la memoria después de que durante el proceso de recuperación de SQL?

--- editado el 13 jul 2009

Permítanme desarrollar mi pregunta. Tengo 1 servidor dB y 1 servidor de aplicaciones. Cuando emito una consulta de selección en la solicitud, los datos se desplazarán desde el servidor db al servidor de aplicaciones.

Creo (corríjanme si me equivoco) ResultSet tendrá que esperar hasta recibir todos los registros en la consulta. Incluso si dejamos de ir a buscar el tamaño como 4, para una mesa de registro 1000, que aún así terminar con 1000 registros en la pila de memoria de servidor de aplicaciones, ¿es correcto? Fetch tamaño solamente afecta al número de ida y vuelta desde / hacia el servidor db.

Mi pregunta es, cómo iniciar el procesamiento en ese 4 (o cualquier número) registra inmediatamente después de la llegada al servidor de aplicaciones, y disponer que para liberar memoria en el servidor de aplicaciones?

¿Fue útil?

Solución

Creo que se podría utilizar la misma solución que éste . Un conjunto de resultados desplazable.

Otros consejos

Con un poco más de información que puedo obtener una respuesta más útil.

Si está utilizando MySQL:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
       java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

http://www.oracle.com/ tecnología / tecnología / java / sqlj_jdbc / htdocs / jdbc_faq.html :

java.util.Properties info = new java.util.Properties();
info.put ("user", "scott");
info.put ("password","tiger");
info.put ("defaultRowPrefetch","15");
getConnection ("jdbc:oracle:oci:@",info);

Si está utilizando JDBC puede utilizar un conjunto de resultados con un cursor que iterar a través de un registro a la vez. Es necesario que se asegura entonces que se escribe el código XML en un archivo de un registro a la vez en lugar de utilizar DOM para construir el XML.

Una regla de oro que he aprendido de mi experiencia es que nunca llevar a todos los datos de la base de datos para el servidor de aplicaciones. Una cosa que puede hacer es poner en práctica un procedimiento para la página sus datos.

Puede llevar a una página de datos que contienen alrededor de 1000-5000, los registros de procesos que, por otra parte obtener los datos para la siguiente página.

Un concepto para la exportación de toda la tabla. (Nota para los expertos:. Soy consciente de sus defectos)

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
public class FullTableExport {
    public static String toXML(String s) {
        if (s != null) {
            StringBuilder b = new StringBuilder(s.length());
            for (int i = 0, count = s.length(); i < count; i++) {
                char c = s.charAt(i);
                switch (c) {
                case '<':
                    b.append("&lt;");
                    break;
                case '>':
                    b.append("&gt;");
                    break;
                case '\'':
                    b.append("&#39;");
                    break;
                case '"':
                    b.append("&quot;");
                    break;
                case '&':
                    b.append("&amp;");
                    break;
                default:
                    b.append(c);
                }
            }
            return b.toString();
        }
        return "";
    }
    public static void main(String[] args) throws Exception {
        String table = "CUSTOMER";
        int batch = 100;

        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
            "jdbc:oracle:thin:@server:orcl", "user", "pass");
        PreparedStatement pstmt = conn.prepareStatement(
            "SELECT /*+FIRST_ROWS(" + batch + ") */ * FROM " + table);
        ResultSet rs = pstmt.executeQuery();
        rs.setFetchSize(batch);
        ResultSetMetaData rsm = rs.getMetaData();
        File output = new File("result.xml");
        PrintWriter out = new PrintWriter(new BufferedWriter(
            new OutputStreamWriter(
            new FileOutputStream(output), "UTF-8")), false);
        out.printf("<?xml version='1.0' encoding='UTF-8'?>%n");
        out.printf("<table name='%s'>%n", toXML(table));
        int j = 1;
        while (rs.next()) {
            out.printf("\t<row id='%d'>%n", j++);
            for (int i = 1; i <= rsm.getColumnCount(); i++) {
                out.printf("\t\t<col name='%s'>%s</col>%n", 
                    toXML(rsm.getColumnName(i)), 
                    toXML(rs.getString(i)));
            }
            out.printf("\t</row>%n");
        }
        out.printf("</table>%n", table);
        out.flush();
    }
}

Editar Las deficiencias (gracias @ J. S.):

  • No hay bibliotecas externas utilizadas más allá de la ojdbc
  • Nada está cerrado
  • Una excepción es lanzada genérica
  • Es un método principal
  • Uso de la impresión para la generación de XML
  • Oracle SQL específica
  • contraseña en texto plano
  • Algunas columnas se ven torpe en representación de cadena
  • UTF-8 es demasiado internacional
  • estructura XML huella es grande

¿En qué fase se produce el error OOM, es que en los datos de recuperación o tratamiento de datos de archivo XML?

Si su recuperación de datos, obtener los datos en lotes. Obtener el número total de filas primera, ordenar las selecciona por la clave primaria y limitar las filas seleccionadas a tamaños masticables.

Si su creación en el archivo XML, enviar el nodo XML de cada cliente para System.out.println, no mantenerlo en su memoria. El lanzamiento del programa a través de la línea commad y redireccionar toda la salida a un archivo;

java MyConverter > results.txt

A medida que recorrer todos se guarda en el archivo. El registro

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