我有一个结构为INSERT语句的备份文件。我的方法是编写一个方法来从文件中加载这些语句,并使用JDBC模板来执行它们。
public void restoreFile(File f) throws Exception {
LineIterator it = FileUtils.lineIterator(f, "UTF-8");
try {
while (it.hasNext()) {
String insertStatement = it.nextLine();
if (!insertStatement.startsWith("--") && !insertStatement.isEmpty()) {
insertStatement = insertStatement.replace(";", "");
executeSqlStatement(insertStatement);
}
}
} finally {
it.close();
}
}
public void executeSqlStatement(String sqlStatement) throws Exception {
PreparedStatementCreator statement = new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement statement = connection.prepareStatement(sqlStatement);
return statement;
}
};
getJdbcTemplate().update(statement);
}
在一些情况下,这似乎工作得很好。但是,我插入的一些值是巨大的XML字符串(一些XML超过10K字符)。
当我运行更新功能时,我收到几个文件的错误:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-01704: string literal too long
另一方面,如果我在SQL Developer中运行相同的脚本,则不会发生此错误。
我知道我应该使用带有绑定变量的预准备语句,但由于需求将文件存储为插入,我宁愿不必解析整个文件。我想简单地按原样执行每一行。
有解决方法吗?
编辑:另外,SQL Developer如何处理这些长字符串文字?
答案 0 :(得分:2)
hackatron来了:
public void executeSqlStatement(String sqlStatement) throws Exception {
PreparedStatementCreator statement = new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException {
List<String> params = new ArrayList<>();
if (sqlStatement.length() >= 4000) {
Pattern pattern = Pattern.compile("'(([^'\n]|'')+)'");
Matcher m = pattern.matcher(sqlStatement);
StringBuffer sb = new StringBuffer();
while (m.find()) {
params.add(m.group(1).replace("''", "'"));
m.appendReplacement(sb, "?");
}
m.appendTail(sb);
sqlStatement = sb.toString();
}
PreparedStatement statement = connection.prepareStatement(sqlStatement);
for (int i = 0; i < params.size(); ++i) {
statement.setString(1 + i, params[i]);
}
return statement;
}
};
getJdbcTemplate().update(statement);
}
如您所见:它试图通过提取字符串文字来缩小较大的SQL。