簡體   English   中英

Java程序流程中PreparedStatement的正確處理方法是什么?

[英]What is the right way to deal with the PreparedStatement in the Java program flow?

有兩種使用 PreparedStatement 的方法。

第一種方法在第二種方法中調用。

第一種方法:

protected List<String> findResultsByMandantId(Long mandantId) {
    List<String> resultIds = new ArrayList<>();
    ResultSet rs;
    String sql = "SELECT result_id FROM results WHERE mandant_id = ?";
    PreparedStatement statement = getPreparedStatement(sql, false);
    try {
        statement.setLong(1, mandantId);
        statement.execute();
        rs = statement.getResultSet();

        while (rs.next()) {
            resultIds.add(rs.getString(1));
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
    return resultIds;
}

第二種方法:

protected void findResultLineEntityToDelete(Long mandantId, String title, String context) {
    List<String> resultIds = findResultsByMandantId(mandantId);
    String [] resultIdsArr = resultIds.toArray(String[]::new);
    
    ResultSet rs;

    //String sql = "SELECT * FROM resultline WHERE result_id in (SELECT result_id FROM results WHERE mandant_id =" + mandantId + ")";
    String sql = "SELECT * FROM resultline WHERE result_id in (" + String.join(", ", resultIdsArr)+ ")";
    PreparedStatement statement = getPreparedStatement(sql, false);
    try {
        statement.execute();
        rs = statement.getResultSet();

        while (rs.next()) {
            if (rs.getString(3).equals(title) && rs.getString(4).equals(context)) {
                System.out.println("Titel: " + rs.getString(3) + " " + "Context: " + rs.getString(4));
            }
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

兩種方法都位於其中的 class 擴展了 JDBCBaseManager。

JDBCBaseManager:

private final String url = "jdbc:mysql://localhost:3306/database";
private final String userName = "root";
private final String password = "";
private Connection connection = null;
private PreparedStatement preparedStatement = null;
private int batchSize = 0;


public JDBCBaseManager() {
//      Dotenv env = Dotenv.configure().directory("./serverless").load();
//      url = env.get("DB_PROD_URL");
//      userName = env.get("DB_USER");
//      password = env.get("DB_PW");
}

public void getConnection() {
    try {
        if (connection == null) {
            connection = DriverManager.getConnection(url, userName, password);
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
    try {
        if (connection == null) {
            getConnection();
        }
        if (preparedStatement == null) {
            if (!returnGeneratedKeys) {
                preparedStatement = connection.prepareStatement(sql);
            } else {
                preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                connection.setAutoCommit(false);
            }
        }
        return preparedStatement;
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

public void closeConnection() {
    try {
        if (connection != null && !connection.isClosed()) {
            System.out.println("Closing Database Connection");
            connection.close();
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

public void startBatch(int batchSize) throws SQLException {
    connection.setAutoCommit(false);
    setBatchSize(batchSize);
}

public void commit() {
    try {
        if (connection != null && !connection.isClosed()) {
            connection.commit();
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

public int getBatchSize() {
    return batchSize;
}

public void setBatchSize(int batchSize) {
    this.batchSize = batchSize;
}

第二種方法中的 ResultSet 仍然包含第一種方法的結果。

在執行第二種方法之前,我已經嘗試關閉連接並再次打開它,但隨后出現錯誤:

java.sql.SQLException:語句關閉后不允許操作。

java.sql.SQLNonTransientConnectionException:連接關閉后不允許任何操作。

您能告訴我在這種情況下如何正確處理該語句嗎? 我的 BaseManager 結構是否不正確?

這就是錯誤

public JDBCBaseManager() {

  private PreparedStatement preparedStatement = null;

    public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
      try {
      ......
       if (preparedStatement == null) {
            if (!returnGeneratedKeys) {
                preparedStatement = connection.prepareStatement(sql);
            } else {
                preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                connection.setAutoCommit(false);
            }
        }
        return preparedStatement;

僅在第一次調用方法getPreparedStatement時構建准備語句,因為僅在第一次字段preparedStatement為 null 時。 每次您調用getPreparedStatement方法時,您都會從前一個 SQL 而不是新的收到前一個preparedStatement

取消對if (preparedStatement == null) {的檢查

每次要執行新的 SQL 時,都需要構建新的preparedStatement

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM