Come funziona il PreparedStatement di Java?

Sto pianificando di sostituire gli oggetti Statement eseguiti ripetutamente con gli oggetti PreparedStatement per migliorare le prestazioni. Sto usando argomenti come la funzione MySQL now() e le variabili stringa.

La maggior parte delle query PreparedStatement che ho visto contenevano valori costanti (come 10 e stringhe come "New York" ) come argomenti usati per il ? nelle domande. Come utilizzerei le funzioni come now() e le variabili come argomenti? È necessario usare il ? s nelle query invece dei valori effettivi? Sono abbastanza confuso.

Se hai variabili usa il ‘?’

 int temp = 75; PreparedStatement pstmt = con.prepareStatement( "UPDATE test SET num = ?, due = now() "); pstmt.setInt(1, temp); pstmt.executeUpdate(): 

Produce una statistica SQL che assomiglia a:

 UPDATE test SET num = 75, due = now(); 

Se hai una variabile che proviene da input dell’utente, è essenziale che tu usi il? piuttosto che concatenare le stringhe. Gli utenti potrebbero inserire una stringa maliziosamente, e se si rilascia la stringa direttamente in SQL, è ansible eseguire un comando che non si intende.

Mi rendo conto che questo è abusato, ma lo dice perfettamente:

Piccoli tavoli da Bobby

Non è necessario utilizzare segnaposti in una PreparedStatement. Qualcosa di simile a:

 PreparedStatement stmt = con.prepareStatement("select sysdate from dual"); 

funzionerebbe bene Tuttavia, non è ansible utilizzare un segnaposto e quindi associare una chiamata a una funzione. Qualcosa di simile non può essere usato per chiamare la funzione sysdate:

 PreparedStatement stmt = con.prepareStatement("select ? from dual"); stmt.setSomethingOrOther(1, "sysdate"); 

Se si stanno chiamando funzioni integrate del proprio server SQL, utilizzare PreparedStatement .

Se si stanno chiamando stored procedure che sono state caricate sul server SQL, utilizzare CallableStatement .

Utilizzare i punti interrogativi come segnaposto per i parametri di funzione / procedura che si stanno passando e per i valori di ritorno della funzione che si stanno ricevendo.

Ho sviluppato una funzione che consente di utilizzare parametri denominati nelle query SQL:

 private PreparedStatement generatePreparedStatement(String query, Map parameters) throws DatabaseException { String paramKey = ""; Object paramValue = null; PreparedStatement statement = null; Pattern paramRegex = null; Matcher paramMatcher = null; int paramIndex = 1; try { //Create the condition paramRegex = Pattern.compile("(:[\\d\\w_-]+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); paramMatcher = paramRegex.matcher(query); statement = this.m_Connection.prepareStatement(paramMatcher.replaceAll("?"), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); //Check if there are parameters paramMatcher = paramRegex.matcher(query); while (paramMatcher.find()) { paramKey = paramMatcher.group().substring(1); if(parameters != null && parameters.containsKey(paramKey)) { //Add the parameter paramValue = parameters.get(paramKey); if (paramValue instanceof Date) { statement.setDate(paramIndex, (java.sql.Date)paramValue); } else if (paramValue instanceof Double) { statement.setDouble(paramIndex, (Double)paramValue); } else if (paramValue instanceof Long) { statement.setLong(paramIndex, (Long)paramValue); } else if (paramValue instanceof Integer) { statement.setInt(paramIndex, (Integer)paramValue); } else if (paramValue instanceof Boolean) { statement.setBoolean(paramIndex, (Boolean)paramValue); } else { statement.setString(paramIndex, paramValue.toString()); } } else { throw new DatabaseException("The parameter '" + paramKey + "' doesn't exists in the filter '" + query + "'"); } paramIndex++; } } catch (SQLException l_ex) { throw new DatabaseException(tag.lib.common.ExceptionUtils.getFullMessage(l_ex)); } return statement; } 

Puoi usarlo in questo modo:

 Map pars = new HashMap<>(); pars.put("name", "O'Really"); String sql = "SELECT * FROM TABLE WHERE NAME = :name";