2012-05-04 34 views
5

我需要從我的數據庫中的某些隨機表中提取數據,並插入到其他數據庫中的類似表中。使用spring jdbctemplate提取數據以加載到不同的數據庫中

我不清楚如何編寫一個可處理所有表的通用方法。

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

請定義您通過「類似的表」的意思 - 難道它們具有相同的結構,唯一不同的是他們在或根本的結構不同的數據庫? –

+0

同樣的結構。對於如我有表A,B,C中DB1它們都具有不同的結構,我需要這些表歸檔到DB2具有表A,B和C – vikknp

回答

1

說實話,JdbcTemplate不是這類任務的最佳選擇。您需要對ResultSet進行一次性處理以創建插入SQL,並且使用JdbcTemplate(據我所知)沒有任何意義。

無論如何,這是我怎麼會做你想要的副本純JDBC(你可以採取同樣的原則,並擠入JdbcTemplate如果你想):

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

最重要的一點是什麼發生在createInsertSqlsetParameters方法中,這兩種方法都使用ResultSetMetaData來執行其操作。你需要與這些有點取決於數據庫您使用的玩,但他們會是這個樣子:

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

和:

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

注意這隻能如果源和目標數據庫具有相同結構的表。如果它們發生變化,您必須開始定義兩者之間的映射關係,此時您最好購買ETL工具。

如下評論

插入/更新的東西是相當多的困難。

DatabaseMetaData您需要獲取主鍵並查詢源表和目標表,確保查詢按主鍵列排序。

然後,當您迭代源結果集時,您需要檢查目標結果集以查看主鍵列是否匹配或更大的排序順序,從而創建插入或更新SQL。

例如,如果你有在源表1,2,3,4,第7和在你有1,2,4,5,6則目標表簡單整數鍵:

  • 1 =更新
  • 2 =更新
  • 3,因爲這4之前是可以安全地插入
  • 4 =更新
  • 需要迭代目標的結果集,直到你已經走過去的6就可以知道前
  • 7確定7是插入。

對不起,如果不那麼清楚,很難在靜態文本中解釋。

+0

謝謝,這個完美的作品,如果我需要在目標表中插入的記錄。我還需要保留一個檢查,如果具有相同主鍵的記錄已經存在於目標表中,我需要更新而不是插入。 – vikknp

+0

查看如何做插入或更新的標題爲**下面的註釋**上面的解釋。 –

0

調用

this.jdbcTemplate.setDateSource(sourceDB) 

之前讀取數據

this.jdbcTemplate.setDateSource(targetDB) 

寫之前。在Spring

註冊多個數據源和使用這樣的

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

這是怎麼回事,以幫助這兩個之間複製數據數據庫(除了你明顯需要兩個連接)? –

+0

正是我知道我將如何使用spring配置多個數據源。但是,當我想從中獲取數據的表不同時,如何以通用方式提取數據。 – vikknp

相關問題