Prepared Statement et requête

Solène -  
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour, j'ai créer une fonction afin que l'utilisateur puisse modifier n'importe quelle valeur d'une table donnée. Cela implique alors que la colonne contenant la valeur à modifier est fournit par l'utilisateur, j'utilise pour cela un Prepared statement mais ça bloque j'ai une erreur me disant qu'il y a un problème de requête : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax

Ma requête est :
sql="UPDATE vehicules SET ?=? WHERE Immatriculation = ?;";

Je sais que c'est le nom de la colonne qui cloche, parce que quand je spécifie le nom de la colonne ça marche :
sql="UPDATE vehicules SET Kilometrage=? WHERE Immatriculation = ?;"; //fonctionne

D'autre part je me pose aussi une autre question mon tableau contient des entiers mais aussi des chaînes de caractères, et vu qu'il faut spécifier de quelle type est la valeur à modifier je me retrouve bloquée.
De l'aide serait la bienvenue,

Cordialement,
A voir également:

2 réponses

KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bonjour,

Je pense que tu devrais lister exhaustivement les colonnes que tu peux manipuler, les associer au type de données qu'elle doit contenir, et éventuellement les alias avec lesquels les utilisateurs peuvent y accéder.

Pour faire tout ça je pense à un enum. Si tu veux un exemple merci d'indiquer dans quelle version de Java tu codes.
0
Solène
 
Bonjour, oui je veux bien un exemple s'il te plaît ^^
Ma version c'est "Version 8 mise à jour 74" je sais pas si c'est ça que tu veux ?
0
Solène
 
Je viens de voir qu'il y a également ça comme détails :

build 1.8.0_74-b02
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bonjour,

Quand je demandais la version de Java dans laquelle tu codes c'est en terme de fonctionnalités. Tu as une version Java 8 (la plus récente) donc tout ce que je te proposes fonctionnera, si tu programmais avec des versions plus anciennes (Java 7, Java 6...) certains codes ne compileraient pas à cause de nouvelles classes, nouvelles méthodes, ou même nouvelles syntaxes qui n'existaient pas dans les versions plus anciennes.

Comme tu es en Java 8, j'ai mis des expressions lambda car c'est très pratique dans ton cas, si tu n'es pas familière avec ça tu peux regarder cet article : Java - Les Structures fonctionnelles

Bref, un exemple. Voici une enum de paramétrage qui permet de définir toutes les colonnes qui t'intéresse et leur comportement.
Pour l'exemple j'ai mis deux colonnes : KILOMETRAGE qui impose d'avoir un entier positif dans le JTextField et fait un setInt pour le Statement et IMMATRICULATION qui autorise lettres et chiffres et fait un setString.

import java.sql.*;

public enum VehiculeColonne {
    KILOMETRAGE("Kilométrage", "kilometrage",
            str -> Integer.parseInt(str) >= 0,
            (stmt, n, str) -> stmt.setInt(n, Integer.parseInt(str))),
    IMMATRICULATION("Immatriculation", "immatricution",
            str -> str.matches("\\w+"),
            (stmt, n, str) -> stmt.setString(n, str));

    private final String description, colonne;
    private final Function<String, Boolean> validator;
    private final StatementSetter setter;

    private VehiculeColonne(String description, String colonne,
            Function<String, Boolean> validator, StatementSetter setter) {
        this.description = description;
        this.colonne = colonne;
        this.validator = validator;
        this.setter = setter;
    }

    public String getTableColonne() {
        return colonne;
    }

    public String getTableColonne(String tableId) {
        return tableId + "." + colonne;
    }

    public boolean isValid(String value) {
        try {
            return validator.apply(value);
        } catch (RuntimeException e) {
            return false;
        }
    }

    public void setParameter(PreparedStatement statement,
            int index, String param) throws SQLException {
        setter.accept(statement, index, param);
    }

    @Override
    public String toString() {
        return description;
    }
}

import java.sql.*;

@FunctionalInterface
public interface StatementSetter {
    void accept(PreparedStatement statement, int index, String param) throws SQLException;
}

Et voici un petit code de test, qui remplit une ComboBox avec toutes les valeurs de l'enum, vérifie que le champ rentré dans le TextField correspond bien au format attendu, et effectue la requête quand on appuie sur le bouton. Le point le plus important à remarquer c'est qu'on appelle à chaque fois l'enum pour savoir quoi faire, c'est elle qui contient la connaissance sur le traitement à effectuer, donc il faut juste rajouter des valeurs dans l'enum pour enrichir ton programme.

Remarque : le code qui fait la requête est désactivé car je n'ai pas d'objet Connection dans mon code de test, ça va juste afficher une pop-up.


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.sql.*;
import javax.swing.*;

public class Test {

    private static void validate(VehiculeColonne colonne,
            JTextField textField, JButton button) {
        if (colonne.isValid(textField.getText())) {
            textField.setBackground(Color.GREEN);
            button.setEnabled(true);
        } else {
            textField.setBackground(Color.RED);
            button.setEnabled(false);
        }
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        JTextField textField = new JTextField();
        JComboBox<VehiculeColonne> comboBox =
                new JComboBox<VehiculeColonne>();
        JButton button = new JButton("Requête SQL");

        for (VehiculeColonne colonne : VehiculeColonne.values()) {
            comboBox.addItem(colonne);
            comboBox.addItemListener(itemEvent -> {
                if (itemEvent.getStateChange() == ItemEvent.SELECTED) {
                    validate(colonne, textField, button);
                }
            });
        }

        textField.addKeyListener(new KeyListener() {
            @Override
            public void keyReleased(KeyEvent e) {
                validate((VehiculeColonne) comboBox.getSelectedItem(),
                        textField, button);
            }

            public void keyTyped(KeyEvent e) {
            }

            public void keyPressed(KeyEvent e) {
            }
        });

        button.addActionListener(actionEvent -> {
            VehiculeColonne colonne =
                    (VehiculeColonne) comboBox.getSelectedItem();
            String sql = "UPDATE vehicules SET "
                    + colonne.getTableColonne() + " = ?";
            JOptionPane.showMessageDialog(frame, sql);
/*
            try (Connection con = null) { // TODO
                PreparedStatement stmt = con.prepareStatement(sql);
                colonne.setParameter(stmt, 1, textField.getText());
            } catch (SQLException e) {
                e.printStackTrace();
            }
//*/
        });

        frame.add(comboBox, BorderLayout.NORTH);
        frame.add(textField, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);
        frame.setSize(200, 120);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

La confiance n'exclut pas le contrôle
0