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:
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";