我需要从我的数据库中的一些随机表中提取数据,并插入到不同数据库中的类似表中。
我不清楚如何编写一个可以处理所有表的泛型方法。
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 :(得分: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);
}
重要的一点是createInsertSql
和setParameters
方法中发生的事情,它们都使用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 :(得分:0)
致电
this.jdbcTemplate.setDateSource(sourceDB)
在读取数据之前
和
this.jdbcTemplate.setDateSource(targetDB)
在写作之前。
在你的春天注册多个DataSource并使用类似的东西
@Autowired
@Qualifier("writeDataSource")
public void setDataSource(DataSource writeDataSource) {
this.jdbcTemplate = new JdbcTemplate(writeDataSource);
}