0

当我尝试使用 Java 将数据放入我的 Oracle 数据库时,我遇到了需要避免特殊字符或转义它们的问题。我敢肯定,有一种聪明的方法可以使用我不知道的功能来解决这个问题。

我的问题示例:

电影名称:加勒比海盗:亡灵箱

标题有一个“ ' ”,表示将由 Oracle 数据库处理。当使用 Java 变量将其放入 INSERT 语句时,它不能被转义。

我想进入我的数据库的数据来自电影数据库 (TMDB),我正在使用一个名为 themoviedbapi 的包装器。使用该包装器,我为自己编写了一个小程序来获取数据并将其放入我的数据库中。

[...] for (int i = 0; i < tmdb_max_id; i++) {
            int movie_count = 0;

            try {

                MovieDb movie_name = movies.getMovie(i, "en");
                String imdb_id = movie_name.getImdbID();

                db.processInsert("INSERT INTO TMDB_TEST_MOVIES (TMDB_ID, ORIGINAL_TITLE, IMDB_ID) "+ 
                                    "VALUES ('"+i+"', '"+movie_name+"', '"+imdb_id+"')");

                i++;

            } catch (RuntimeException e) {
                System.err.println("Error getting movie with ID " + i);
                continue;
            } catch (SQLException sqle) {
                System.err.println(sqle+" SQL ERROR at movie with ID"+i);
                throw sqle;
            }[...]

到达电影时(见上文)我得到的是以下异常:

Exception in thread "main" java.sql.SQLSyntaxErrorException: ORA-00917: Missing comma 

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:195)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1036)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1916)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1878)
at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:318)
at database.DatabaseConnect.processInsert(DatabaseConnect.java:24)
at tmdb_api_to_db.main.main(main.java:65)

这可能是因为我遇到了非转义特殊字符的特定问题。一位同事告诉我,有一种方法可以绑定变量以避免 SQL 注入,这也可以解决我的问题,但是 - 老实说 - 我搜索了这样的功能,但未能成功地将其转移到我的具体问题上。

理想的解决方案是,如果有人能告诉我如何构建我的 INSERT 语句以避免上述异常......

我完全愿意接受任何方式的批评和建议!

正如您可能注意到的:我对 SQL 和 Java 的了解都生锈得要死,所以请放纵 :)

4

2 回答 2

1

这是我解决它的方法-感谢@Thomas和@Marmite Bomber :)

我将 PreparedStatement 添加到我的 DatabaseClass

package database;

import java.sql.*;


public class DatabaseConnect {

    private Connection con;

    public void connect(String user, String password, String dbUrl) 
           throws ClassNotFoundException, SQLException
{
    Class.forName("oracle.jdbc.driver.OracleDriver");
    con = DriverManager.getConnection(dbUrl, user, password);
}

public void disconnect() throws SQLException
{
    con.close();
}

public void processInsert(String sql) throws SQLException
{
    Statement stmt = con.createStatement();
    stmt.execute(sql);
    stmt.close();
}

public ResultSet processQuery(String sql) throws SQLException
{
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(sql);
    return rs;
}

public PreparedStatement prepareStatement(String sql) throws SQLException{
    PreparedStatement ps = con.prepareStatement(sql);
    return ps;
}

}

并像这样在我的 Main 中使用它:

[...]PreparedStatement ps = db.prepareStatement("INSERT INTO TMDB_TEST_MOVIES 
       (TMDB_ID, ORIGINAL_TITLE, IMDB_ID) VALUES (?,?,?)");[...]

[...]for (int i = 0; i < tmdb_max_id; i++) {

            try {

                MovieDb movie_name = movies.getMovie(i, "en");
                String original_title = movie_name.getOriginalTitle();
                String imdb_id = movie_name.getImdbID();

                  ps.setInt(1,i);
                  ps.setString(2,original_title);
                  ps.setString(3,imdb_id);
                  ps.executeUpdate();


                i++;

                } catch (RuntimeException e) {
                continue;
            } catch (SQLException sqle) {
                throw sqle;
            }

        }[...]

希望这对寻找该问题的人有所帮助...再次欢呼并感谢!

于 2017-01-30T18:23:00.013 回答
0

只需在您的字符串中添加一个撇号即可转义。例子:

        String movie_name = "Pirates of the Caribbean: Dead Man's Chest";
        if (movie_name.contains("'")){
            movie_name = movie_name.replaceAll("'", "''");
        }
于 2017-01-30T17:28:35.373 回答