jump to navigation

Actualizacion – Copiar datos entre tablas marzo 2, 2007

Posted by superpiwi in Java.
trackback

Con respecto al post

copiar tablas entre bases de datos

he ampliado la funcionalidad de las clases para poder generar el script SQL con las sentencias insert y permite ahora guardarlas en un fichero. Esto nos permite por ejemplo ejecutarlas a posteriori mediante sqlplus:

sqlplus @<fichero.sql>

Los cambios son los siguientes:

Se añade la siguiente variable a la clase DatabaseUtil.java

/**
* Token_final para sentencias SQL
*/
String END_SQL=";";

Y añadimos el metodo:


/**
* Genera el DML de insercion de una tabla. (para utilizar con sqlplus @fichero.sql)
* @param tablename nombre de la tabla.
* @param source conexion con la base de datos.
* @param deleteTarget indica si se debe o no incluir la sentencia DELETE.
* @param out Fichero donde guardar (no se utiliza)
* @throws Exception excepcion levantada en caso de error.
*/
public String generarSQL(String tablename, Connection source, boolean deleteTarget,FileOutputStream out)
throws Exception
{
StringBuffer sql = new StringBuffer();
ResultSet rs = null;
Statement stmt = null;
ResultSetMetaData metadata = null;
String[] columnas = null;
Vector valores = null;
//Vector SENTENCIAS_A_EJECUTAR = null;
Statement stmt2 = null;
String tablename2 = null;
int[] resultados=null;
try
{
// invocar al recolector de basura
System.gc();
long time = System.currentTimeMillis();
DatabaseUtil.debug(DatabaseUtil.class.getName(), "generarSQL", "Generando SQL...", 6, null, null);
sql.append("\r\n-- Generado con DatabaseUtil -- TABLENAME: "+tablename+"\r\n\r\n");
tablename2 = tablename;
// crear conexion con el origen.
DatabaseUtil.debug(DatabaseUtil.class.getName(), "generarSQL", "creando conexion con el origen...", 6, null, null);
try
{
stmt = source.createStatement();
}
catch(Exception e)
{
String error = e.getMessage();
DatabaseUtil.error(DatabaseUtil.class.getName(), "generarSQL", "No se pudo establecer la conexion con el origen : "+error, 6, null, null);
throw new Exception("No se pudo establecer la conexion origen : "+error);
}
DatabaseUtil.debug(DatabaseUtil.class.getName(), "generarSQL", "creando origen creada...", 6, null, null);
// Contabilizar el numero de registros
String SENTENCIA_SQL = "SELECT COUNT(*) FROM "+tablename;
rs = stmt.executeQuery(SENTENCIA_SQL);
rs.next();
String numero_registros = rs.getString(1);
if (rs!=null) rs.close();
// TODO: cambiar esta parte pq funciona pero no es adecuada, hay una clase que nos devuelve el metadato de columnas de una tabla
// sin necesidad de emplear el SELECT * sino directamente analizando el esquema de la base de datos
// ejecutar la consulta para recuperar los nombres de las columnas.
SENTENCIA_SQL = "SELECT * FROM "+tablename;
rs = stmt.executeQuery(SENTENCIA_SQL);
// recuperamos los metadatos
metadata = rs.getMetaData();
int numero_columnas = metadata.getColumnCount();
DatabaseUtil.debug(DatabaseUtil.class.getName(), "generarSQL", "La tabla tiene "+numero_columnas+" columnas", 6, null, null);
// las almacenamos en un Array de Strings.
columnas = new String[numero_columnas];
for (int i=1; i<=numero_columnas;i++)
{
String columna = metadata.getColumnName(i);
columnas[i-1] = columna;
}
// Construimos las sentencias INSERTs para la otra tabla destino...
//SENTENCIAS_A_EJECUTAR = new Vector();
if (deleteTarget)
{
String DELETE = "DELETE FROM "+tablename2+this.END_SQL;
//sql.append(DELETE);
//SENTENCIAS_A_EJECUTAR.addElement(DELETE);
System.out.println(DELETE);
DELETE=DELETE+"\r\n";
if (out!=null) out.write(DELETE.getBytes());
}
while (rs.next())
{
String INSERT = "INSERT INTO "+tablename2+"(";
// recuperamos el valor de todos los registros...
valores = new Vector();
for (int j=1;j<=numero_columnas;j++)
{
INSERT=INSERT+""+columnas[j-1]+",";
String dato = rs.getString(columnas[j-1]);
if (dato==null) dato="";
if (dato!=null)
{
// esto se hace para evitar errores a la hora de insertar campos numericos.
if (dato.equals("null")) dato="";
}
valores.add(dato);
}
//end for
if (INSERT.endsWith(",")) INSERT=INSERT.substring(0,INSERT.length()-1);
INSERT=INSERT+") VALUES (";
// Insertamos los valores...
for (int k=0;k<valores.size();k++)
{
String valor = (String) valores.elementAt(k);
//
// BUG: se evita la insercion de valores que contengan "'" para ello se escapa el campo "''".
//
//valor = Replacement.escape(valor);
INSERT = INSERT+"'"+valor+"',";
}
if (INSERT.endsWith(",")) INSERT=INSERT.substring(0,INSERT.length()-1);
INSERT=INSERT+")";
// String tenemos la sentencia INSERT que almacenamos el el vector de sentencias...
//sql.append(INSERT+this.END_SQL);
//SENTENCIAS_A_EJECUTAR.addElement(INSERT+this.END_SQL);
INSERT = INSERT+this.END_SQL;
System.out.println(INSERT);
INSERT = INSERT+"\r\n";
if (out!=null) out.write(INSERT.getBytes());
}
long time_end = System.currentTimeMillis();
long total = time_end - time;
String tiempo = tablename+", Time: "+total+" ms";
DatabaseUtil.debug(DatabaseUtil.class.getName(), "copyTable", tiempo, 6, null, null);
sql.append("\r\n--generado con DatabaseUtil, "+tiempo+"\r\n");
String SQL_ALL = sql.toString();
return SQL_ALL;
}
catch(Exception e)
{
DatabaseUtil.error(DatabaseUtil.class.getName(), "generarSQL", "Ha ocurrido un error ejecutando proceso Batch para la tabla "+tablename, 6, null, null);
DatabaseUtil.error(DatabaseUtil.class.getName(), "generarSQL", e.toString(), 6, null, null);
throw e;
}
finally
{
// cerramos los flujos abiertos
try
{
if (rs!=null) rs.close();
}
catch(Exception e)
{
;
}
try
{
if (stmt!=null) stmt.close();
}
catch(Exception e)
{
;
}
try
{
if (stmt2!=null) stmt2.close();
}
catch(Exception e)
{
;
}
}
}
//----

Sobre la clase Migracion.java añadimos el metodo:


/**
* @modification - <<AÑADIDO 1 MARZO>> Para generar el SQL de las sentencias
* Genera el SQL de migracion de las tablas.
* @param out fichero donde guardar las sentencias para posteriormente ejecutar con sqlplus @nombrefichero.sql
* @return un SQL con las sentencias DDL de insercion de las tablas (si esta habilitado aunque no se recomienda por problemas de memoria) + 1 informe de tiempos.
* @throws Exception excepcion levantada en caso de error.
*/
public String generarSQL(FileOutputStream out) throws Exception
{
StringBuffer sbsql = new StringBuffer();
Connection ORIGEN=null;
DatabaseUtil util = null;
try
{
imprimirParametros();
Migracion.debug(Migracion.class.getName(), "migrar", "@obtener conexiones", 6, null, null);
Class.forName(this.odriver);
ORIGEN=DriverManager.getConnection(this.ourl,this.ouser,this.opass);
Migracion.debug(Migracion.class.getName(), "migrar", "conexion origen:"+ORIGEN, 6, null, null);
Class.forName(this.ddriver);
Migracion.debug(Migracion.class.getName(), "migrar", "@Procesar tablas", 6, null, null);
util = new DatabaseUtil();
util.setVerbose(verbose);
// obtener tablas
StringTokenizer st = new StringTokenizer(this.otables,",");
while (st.hasMoreTokens())
{
String TABLENAME = st.nextToken();
Migracion.debug(Migracion.class.getName(), "migrar", "Procesando tabla:"+TABLENAME+"...", 6, null, null);
// recuperar el SQL
String SQL = util.generarSQL(TABLENAME, ORIGEN, true, out);
sbsql.append(SQL);
}
return sbsql.toString();
}
catch(Exception e)
{
throw e;
}
finally
{
try
{
if (ORIGEN!=null) ORIGEN.close();
}
catch(Exception f)
{
;
}
}
}
//----

Ahora si queremos guardar en disco las sentencias SQL bastaria con invocar:


Migracion m2 = new Migracion(...lo que sea...)...
File fout = new File("/home/jose/Desktop/migracion.sql");
FileOutputStream fo = new FileOutputStream(fout);
String SQL_TABLAS = m2.generarSQL(fo);
System.out.println(SQL_TABLAS);
fo.close();

Puede que no sea lo mas optimo pero funciona.

Comentarios»

1. armando - noviembre 21, 2007

tengo un problema estoy generando un proyect de base de datos de MySQL con Java y quisiera ver si alguien sabe como puedo guardar datos en una tabla en tiempo real.

esto quiere decir que al momento de ejecutar mi proyecto y generar mi frame y me aparesca la tabla le agregue items y estos sehan almacenados

2. superpiwi - noviembre 27, 2007

no te entiendo muy bien, pero si que puedes guardar y consultar datos en tiempo real, aunque si lo que quieres es via web, te aconsejo que le eches un vistazo a ajax.


Deja un comentario