2012-05-04 8 views
5

Ho bisogno di estrarre i dati da alcune tabelle casuali dal mio database e inserirli in tabelle simili in un altro database.Estrarre i dati utilizzando spring jdbctemplate per caricare in un altro database

Non sono chiaro su come posso scrivere un metodo generico in grado di gestire tutti i tavoli.

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

Si prega di definire cosa si intende per "tabelle simili" - hanno la stessa struttura e l'unica differenza è il database in cui si trovano o la struttura è diversa? –

+0

Stessa struttura. Ad esempio, ho tabelle A, B, C in DB1 che hanno tutte una struttura diversa, e ho bisogno di archiviare queste tabelle in DB2 che ha le tabelle A, B e C. – vikknp

risposta

1

Per essere onesti, JdbcTemplate non è la scelta migliore per questo tipo di compito. È necessario eseguire una singola elaborazione di ResultSet per creare l'SQL di inserimento e non c'è alcun punto in cui è possibile farlo utilizzando JdbcTemplate (per quanto ne so).

In ogni caso, questo è come mi piacerebbe fare la copia che si desidera in puro JDBC (si può prendere gli stessi principi e spremere in JdbcTemplate se si vuole):

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

Il bit importante è quello che avviene nei metodi createInsertSql e setParameters, che utilizzano entrambi lo ResultSetMetaData per eseguire le loro operazioni. Avrete bisogno di giocare con questi un po 'a seconda del database che si sta utilizzando, ma ti guarda qualcosa di simile:

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

E:

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

notare che questo funziona solo se l'origine e la i database di destinazione hanno tabelle strutturate in modo identico. Se variano, dovrai iniziare a definire i mapping tra i due, a quel punto starai meglio acquistando uno strumento ETL.

seguente commento

L'inserimento/aggiornamento cosa è abbastanza molto più difficile.

Da DatabaseMetaData è necessario ottenere la chiave primaria e interrogare sia le tabelle di origine che di destinazione assicurandosi che gli ordini di query siano eseguiti dalle colonne della chiave primaria.

Quindi, mentre si esegue l'iterazione sul set di risultati di origine, è necessario controllare il set di risultati di destinazione per verificare se le colonne della chiave primaria corrispondono o sono più grandi nell'ordinare, creando in modo inserto o aggiornamento sql in modo coerente.

Ad esempio se si ha semplici chiavi intere nella tabella sorgente 1, 2, 3, 4, 7 e nella tabella di destinazione si aveva 1, 2, 4, 5, 6 allora:

  • 1 = aggiornare
  • 2 = aggiornamento
  • 3 perché è prima di 4 può tranquillamente essere un inserto
  • 4 = aggiornamento
  • 7 è necessario scorrere il set di risultati di destinazione prima che siano trascorse oltre 6 prima di poter sapere per certo che 7 è un inserto.

Scusate se non è chiaro, è difficile da spiegare nel testo statico.

+0

Grazie, funziona perfettamente se ho bisogno di inserire i record nella tabella di destinazione. Devo anche mantenere un controllo, se il record con la stessa chiave primaria esiste già nella tabella di destinazione, ho bisogno di aggiornare piuttosto che inserire. – vikknp

+0

Vedere la spiegazione di come inserire o aggiornare nella sezione intitolata ** Following Comment ** sopra. –

0

chiamata la

this.jdbcTemplate.setDateSource(sourceDB) 

prima di dati letti

e

this.jdbcTemplate.setDateSource(targetDB) 

prima di scrivere.

registrare più DataSources nella vostra primavera e usare qualcosa di simile

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

Come questo aiuterà a copiare i dati tra i due database (diversi da quelli che ovviamente richiedono due connessioni)? –

+0

Esattamente so come configurerò più origini dati utilizzando la molla. Ma come estrarre i dati in modo generico quando le tabelle da cui voglio recuperare i dati sono diverse. – vikknp

Problemi correlati