Publié le 10/07/2010
Auteur fobec
Réseaux sociaux
0 partages
0 tweets
0 plus
0 commentaires

Nommer les parametres d'une requete SQL avec PreparedStatement

En complément à l'article sur la connexion à une base de données avec le driver JDBC, abordons l'édition de requętes SQL. Sur une opération de type SELECT, les paramètres sont définis avec le nom du champs et un point d'interrogation pour la valeur, ci-dessous un exemple
PreparedStatement ps = connection.prepareStatement("select * from table where 
field1 = ? and field2 = ? and field3 = ?");
ps.setString(1, value1);
ps.setString(2, value2);
ps.setString(3, value3);

Ecrire une requete SQL avec des paramètres

Fixer les valeurs des paramètres d'après leur index devient rapidement un casse-tête sur des requêtes un peu plus complexes. Une solution élégante est de donner un nom à chaque paramètre.
La class NamedParameterStatement trouvée sur javaworld donnera de la clarté au code et est facile à mettre en œuvre. Voici un exemple sur une requête SQL pour une recherche sur 2 champs:

String query="SELECT * from my_table 
WHERE tab_nom=:tab_nom AND tab_prenom=:tab_prenom";
NamedParameterStatement p=new NamedParameterStatement(connexion, query);
p.setString("tab_nom", "fobec");
p.setString("tab_prenom", "christian");
 

Donner un nom aux paramètres SQL en JAVA

Que ce soit sur une base de données MySQL ou que ce soit sur une base Firebird, il est pénible d'avoir des points d'interrogation à la place des valeurs à insérer dans la requête. Ci-dessous un class trouvée sur internet permetant de palier à cela et de nommer les paramètres dans un requête en faisant précéder la valeur par un double-point.
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
 
/*
 * Nommer les paramètres dans une requete SQL
 * @author adam_crume
 */
public class NamedParameterStatement {
    /** The statement this object is wrapping. */
    private final PreparedStatement statement;
 
    /** Maps parameter names to arrays of ints which are the parameter indices.
*/
    private final Map indexMap;
 
 
    /**
     * Creates a NamedParameterStatement.  Wraps a call to
     * c.{@link Connection#prepareStatement(java.lang.String) prepareStatement}.
     * @param connection the database connection
     * @param query      the parameterized query
     * @throws SQLException if the statement could not be created
     */
    public NamedParameterStatement(Connection connection, String query) throws SQLException {
        indexMap=new HashMap();
        String parsedQuery=parse(query, indexMap);
        statement=connection.prepareStatement(parsedQuery);
    }
 
 
    /**
     * Parses a query with named parameters.  The parameter-index mappings are put into the map, and the
     * parsed query is returned.  DO NOT CALL FROM CLIENT CODE.  This method is non-private so JUnit code can
     * test it.
     * @param query    query to parse
     * @param paramMap map to hold parameter-index mappings
     * @return the parsed query
     */
    static final String parse(String query, Map paramMap) {
        // I was originally using regular expressions, but they didn't work well for ignoring
        // parameter-like strings inside quotes.
        int length=query.length();
        StringBuffer parsedQuery=new StringBuffer(length);
        boolean inSingleQuote=false;
        boolean inDoubleQuote=false;
        int index=1;
 
        for(int i=0;i<length;i++) {
            char c=query.charAt(i);
            if(inSingleQuote) {
                if(c=='\'') {
                    inSingleQuote=false;
                }
            } else if(inDoubleQuote) {
                if(c=='\"') {
                    inDoubleQuote=false;
                }
            } else {
                if(c=='\'') {
                    inSingleQuote=true;
                } else if(c=='\"') {
                    inDoubleQuote=true;
                } else if(c==':' && i+1<length &&
                        Character.isJavaIdentifierStart(query.charAt(i+1))) {
                    int j=i+2;
                    while(j<length && Character.isJavaIdentifierPart(query.charAt(j))) {
                        j++;
                    }
                    String name=query.substring(i+1,j);
                    c='?'; // replace the parameter with a question mark
                    i+=name.length(); // skip past the end if the parameter
 
                    List indexList=(List)paramMap.get(name);
                    if(indexList==null) {
                        indexList=new LinkedList();
                        paramMap.put(name, indexList);
                    }
                    indexList.add(new Integer(index));
 
                    index++;
                }
            }
            parsedQuery.append(c);
        }
 
        // replace the lists of Integer objects with arrays of ints
        for(Iterator itr=paramMap.entrySet().iterator(); itr.hasNext();) {
            Map.Entry entry=(Map.Entry)itr.next();
            List list=(List)entry.getValue();
            int[] indexes=new int[list.size()];
            int i=0;
            for(Iterator itr2=list.iterator(); itr2.hasNext();) {
                Integer x=(Integer)itr2.next();
                indexes[i++]=x.intValue();
            }
            entry.setValue(indexes);
        }
 
        return parsedQuery.toString();
    }
 
 
    /**
     * Returns the indexes for a parameter.
     * @param name parameter name
     * @return parameter indexes
     * @throws IllegalArgumentException if the parameter does not exist
     */
    private int[] getIndexes(String name) {
        int[] indexes=(int[])indexMap.get(name);
        if(indexes==null) {
            throw new IllegalArgumentException("Parameter not found: "+name);
        }
        return indexes;
    }
 
 
    /**
     * Sets a parameter.
     * @param name  parameter name
     * @param value parameter value
     * @throws SQLException if an error occurred
     * @throws IllegalArgumentException if the parameter does not exist
     * @see PreparedStatement#setObject(int, java.lang.Object)
     */
    public void setObject(String name, Object value) throws SQLException {
        int[] indexes=getIndexes(name);
        for(int i=0; i < indexes.length; i++) {
            statement.setObject(indexes[i], value);
        }
    }
 
 
    /**
     * Sets a parameter.
     * @param name  parameter name
     * @param value parameter value
     * @throws SQLException if an error occurred
     * @throws IllegalArgumentException if the parameter does not exist
     * @see PreparedStatement#setString(int, java.lang.String)
     */
    public void setString(String name, String value) throws SQLException {
        int[] indexes=getIndexes(name);
        for(int i=0; i < indexes.length; i++) {
            statement.setString(indexes[i], value);
        }
    }
 
 
    /**
     * Sets a parameter.
     * @param name  parameter name
     * @param value parameter value
     * @throws SQLException if an error occurred
     * @throws IllegalArgumentException if the parameter does not exist
     * @see PreparedStatement#setInt(int, int)
     */
    public void setInt(String name, int value) throws SQLException {
        int[] indexes=getIndexes(name);
        for(int i=0; i < indexes.length; i++) {
            statement.setInt(indexes[i], value);
        }
    }
 
 
    /**
     * Sets a parameter.
     * @param name  parameter name
     * @param value parameter value
     * @throws SQLException if an error occurred
     * @throws IllegalArgumentException if the parameter does not exist
     * @see PreparedStatement#setInt(int, int)
     */
    public void setLong(String name, long value) throws SQLException {
        int[] indexes=getIndexes(name);
        for(int i=0; i < indexes.length; i++) {
            statement.setLong(indexes[i], value);
        }
    }
 
 
    /**
     * Sets a parameter.
     * @param name  parameter name
     * @param value parameter value
     * @throws SQLException if an error occurred
     * @throws IllegalArgumentException if the parameter does not exist
     * @see PreparedStatement#setTimestamp(int, java.sql.Timestamp)
     */
    public void setTimestamp(String name, Timestamp value) throws SQLException
{
        int[] indexes=getIndexes(name);
        for(int i=0; i < indexes.length; i++) {
            statement.setTimestamp(indexes[i], value);
        }
    }
 
 
    /**
     * Sets a parameter.
     * @param name  parameter name
     * @param value parameter value
     * @throws SQLException if an error occurred
     * @throws IllegalArgumentException if the parameter does not exist
     * @see PreparedStatement#setTimestamp(int, java.sql.Timestamp)
     * Christian 20/11/2009
     */
    public void setDate(String name, Date value) throws SQLException
{
        int[] indexes=getIndexes(name);
        for(int i=0; i < indexes.length; i++) {
            statement.setDate(indexes[i], value);
        }
    }
 
    /**
     * Returns the underlying statement.
     * @return the statement
     */
    public PreparedStatement getStatement() {
        return statement;
    }
 
 
    /**
     * Executes the statement.
     * @return true if the first result is a {@link ResultSet}
     * @throws SQLException if an error occurred
     * @see PreparedStatement#execute()
     */
    public boolean execute() throws SQLException {
        return statement.execute();
    }
 
 
    /**
     * Executes the statement, which must be a query.
     * @return the query results
     * @throws SQLException if an error occurred
     * @see PreparedStatement#executeQuery()
     */
    public ResultSet executeQuery() throws SQLException {
        return statement.executeQuery();
    }
 
 
    /**
     * Executes the statement, which must be an SQL INSERT, UPDATE or DELETE
statement;
     * or an SQL statement that returns nothing, such as a DDL statement.
     * @return number of rows affected
     * @throws SQLException if an error occurred
     * @see PreparedStatement#executeUpdate()
     */
    public int executeUpdate() throws SQLException {
        return statement.executeUpdate();
    }
 
 
    /**
     * Closes the statement.
     * @throws SQLException if an error occurred
     * @see Statement#close()
     */
    public void close() throws SQLException {
        statement.close();
    }
 
 
    /**
     * Adds the current set of parameters as a batch entry.
     * @throws SQLException if something went wrong
     */
    public void addBatch() throws SQLException {
        statement.addBatch();
    }
 
 
    /**
     * Executes all of the batched statements.
     *
     * See {@link Statement#executeBatch()} for details.
     * @return update counts for each statement
     * @throws SQLException if something went wrong
     */
    public int[] executeBatch() throws SQLException {
        return statement.executeBatch();
    }
}

Dans vos projets Java et MySql lorsque les requêtes sont assez complexes, n’hésitez pas à nommer les champs. Premièrement, les requêtes devienent plus clairs et simple à comprendre dans le cas d'une évolution futures. Deuxièmement, la syntaxe est exactement la meme avec un driver PDO dans le langage PHP. Donc la même instruction SQL pourra etre utilisée aussi bien dans une application JAVA que sur un site internet en PHP.

Ajouter un commentaire

Les champs marqués d'un * sont obligatoires, les adresses emails se sont pas publiées.

A lire aussi

Réseaux sociaux
Présentation de l'article
Catégorie
java - class
Mise a jour
10/07/2010
Visualisation
vu 2911 fois
Public
Internaute
Auteur de la publication
Fobec
Admin
Auteur de 261 articles
|BIO_PSEUDO|
Commentaires récents

Publié par ammar dans CMS

merci pour ce code , mais ce que je veux savoir c\'est es-ce que possible de récupérer la totalité de code source html de la page original.<br>merci...

Publié par fobec dans java

La boucle de lecture est corrigée et prend en compte l'état pause. Sympa d'avoir signaler l'erreur

Publié par fobec dans logiciel

MAJ: mise en cache du FAI et optimisation du script de Geolocalisation.

Publié par Bonjour dans java

Joli travail!
Par contre, savez vous que votre barre de progression s'arrête à un certain pourcentage?

Publié par Julie dans logiciel

C'est donc un moteur de recherche specialise. On peut vraiment rechercher tous les domaines que l'on veut. Cela permettrait aux gens de ne plus se faire arnaquer. Quelle bonne idee!