通过JDBC执行长插入语句

时间:2018-03-23 20:57:13

标签: java sql oracle jdbc

我有一个结构为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如何处理这些长字符串文字?

1 个答案:

答案 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。