2012-05-04 54 views
5

Necesito extraer datos de algunas tablas aleatorias de mi base de datos, e insertar en tablas similares en una base de datos diferente.Extraer datos utilizando spring jdbctemplate para cargar en una base de datos diferente

No tengo claro cómo puedo escribir un método genérico que pueda manejar todas las tablas.

this.jdbcTemplate.query("select * from TableName", new RowMapper() { 
     @Override 
     public Object mapRow(ResultSet resultSet, int i) throws SQLException { 
      while(resultSet.next()){ 
//    Fetch data in a generic object for later updating in a different schema 
      } 
      return null; //To change body of implemented methods use File | Settings | File Templates. 
     } 
    }); 
+0

Defina lo que quiere decir con "tablas similares": ¿tienen la misma estructura y la única diferencia es la base de datos en la que se encuentran o la estructura difiere? –

+0

Misma estructura. Por ejemplo, tengo las tablas A, B, C en DB1, que tienen una estructura diferente, y necesito archivar estas tablas en DB2, que tiene las tablas A, B y C. – vikknp

Respuesta

1

Para ser honesto, JdbcTemplate no es la mejor opción para este tipo de tarea. Tendrá que hacer un procesamiento por única vez del ResultSet para crear el SQL insertado y realmente no hay ningún punto en el que pueda hacerlo usando JdbcTemplate (hasta donde yo sé).

De todos modos, esta es la forma en que lo haría la copia que desea en el más puro JDBC (se puede tomar los mismos principios y meterla en JdbcTemplate si quieres):

Connection sourceConnection = null; 
Connection destinationConnection = null; 

PreparedStatement selectStatement = null; 
PreparedStatement insertStatement = null; 

ResultSet resultSet = null; 

try 
{ 
    sourceConnection = ... 
    destinationConnection = ... 

    selectStatement = sourceConnection.prepareStatement("SELECT * FROM table"); 
    resultSet = selectStatement.executeQuery(); 

    insertStatement = destinationConnection.prepareStatement(createInsertSql(resultSet.getMetaData())); 

    int batchSize = 0; 
    while (resultSet.next()) 
    { 
    setParameters(insertStatement, resultSet); 
    insertStatement.addBatch(); 
    batchSize++; 

    if (batchSize >= BATCH_EXECUTE_SIZE) 
    { 
     insertStatement.executeBatch(); 
     batchSize = 0; 
    } 
    } 

    insertStatement.executeBatch(); 
} 
finally 
{ 
    JdbcUtils.closeResultSet(resultSet); 

    JdbcUtils.closeStatement(insertStatement); 
    JdbcUtils.closeStatement(selectStatement); 

    JdbcUtils.closeConnection(destinationConnection); 
    JdbcUtils.closeConnection(sourceConnection); 
} 

El bit es lo importante ocurre en los métodos createInsertSql y setParameters, que usan el ResultSetMetaData para realizar sus operaciones. Tendrá que jugar con ellos un poco dependiendo de la base de datos que está utilizando, pero se van a ver algo como:

private String createInsertSql(ResultSetMetaData resultSetMetaData) throws SQLException 
{ 
    StringBuffer insertSql = new StringBuffer("INSERT INTO "); 
    StringBuffer values = new StringBuffer(" VALUES ("); 

    insertSql.append(resultSetMetaData.getTableName()); 

    for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) 
    { 
    insertSql.append(resultSetMetaData.getColumnName(i)); 
    values.append("?"); 

    if (i <= resultSetMetaData.getColumnCount()) 
    { 
     insertSql.append(", "); 
     values.append(", "); 
    } 
    else 
    { 
     insertSql.append(")"); 
     values.append(")"); 
    } 
    } 

    return insertSql.toString() + values.toString(); 
} 

Y:

private void setParameters(PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException 
{ 
    for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) 
    { 
    preparedStatement.setObject(i, resultSet.getObject(i)); 
    } 
} 

Nota Esto sólo funciona si la fuente y las bases de datos de destino tienen tablas estructuradas de manera idéntica. Si varían, tendrá que comenzar a definir las asignaciones entre los dos, y en ese momento es mejor que simplemente compre una herramienta de ETL.

siguiente comentario

La inserción/actualización cosa es mucho más difícil.

Desde el DatabaseMetaData necesitaría obtener la clave principal y consultar las tablas de origen y de destino asegurándose de que la consulta ordene por las columnas de la clave principal.

Luego, al iterar sobre el conjunto de resultados de origen, deberá verificar el conjunto de resultados de destino para ver si las columnas de claves principales coinciden o son mayores en el pedido, creando insertar o actualizar sql de manera correspondiente.

Por ejemplo, si tiene teclas de enteros simples en la tabla de origen 1, 2, 3, 4, 7 y en la tabla de destino que tenía 1, 2, 4, 5, 6 a continuación:

  • 1 = actualizar
  • 2 = actualización
  • 3 porque es antes de las 4 puede ser de forma segura una inserción
  • 4 = actualización
  • 7 que necesita para recorrer el conjunto de resultados de destino hasta que haya pasado el pasado 6 antes de poder saber con certeza que 7 es un inserto.

Lo siento si no está tan claro, es difícil de explicar en texto estático.

+0

Gracias, esto funciona perfectamente si necesito insertar los registros en la tabla de destino. También necesito mantener un control, si el registro con la misma clave principal ya existe en la tabla de destino, necesito actualizar en lugar de insertar. – vikknp

+0

Consulte la explicación de cómo insertar o actualizar en la sección titulada ** Siguiente comentario ** arriba. –

0

Llame al

this.jdbcTemplate.setDateSource(sourceDB) 

antes de datos de lectura

y

this.jdbcTemplate.setDateSource(targetDB) 

antes de escribir.

Registro múltiples DataSources en su primavera y usar algo como esto

@Autowired 
@Qualifier("writeDataSource") 
public void setDataSource(DataSource writeDataSource) { 
    this.jdbcTemplate = new JdbcTemplate(writeDataSource); 
} 
+0

¿Cómo va a ayudar esto con la copia de datos entre los dos? bases de datos (aparte de, obviamente, necesita dos conexiones)? –

+0

Exactamente sé cómo voy a configurar múltiples fuentes de datos con la primavera. Pero cómo extraer los datos de forma genérica cuando las tablas de las que quiero obtener datos son diferentes. – vikknp

Cuestiones relacionadas