java - update - utilisation preparedstatement




Quand devrions-nous utiliser un PreparedStatement au lieu d'un Statement? (6)

  1. La requête est réécrite et compilée par le serveur de base de données

    Si vous n'utilisez pas d'instruction préparée, le serveur de base de données doit analyser et calculer un plan d'exécution pour l'instruction chaque fois que vous l'exécutez. Si vous trouvez que vous exécuterez la même instruction plusieurs fois (avec des paramètres différents), il vaut mieux préparer une fois l'instruction et réutiliser cette instruction préparée. Si vous interrogez la base de données adhoc, cela ne présente probablement aucun avantage.

  2. Protégé contre l'injection SQL

    Ceci est un avantage que vous voulez presque toujours par conséquent une bonne raison d'utiliser un PreparedStatement chaque fois. C'est une conséquence de devoir paramétrer la requête, mais cela rend le fonctionnement beaucoup plus sûr. La seule fois où je peux penser que cela ne serait pas utile, c'est si vous autorisiez des requêtes de base de données ad hoc; Vous pouvez simplement utiliser l'objet Statement si vous faites un prototypage de l'application et que c'est plus rapide pour vous, ou si la requête ne contient aucun paramètre.

Je connais les avantages d’utiliser PreparedStatement , qui sont

  • la requête est réécrite et compilée par le serveur de base de données
  • protection contre l'injection SQL

Mais je veux savoir quand nous l'utilisons au lieu de Statement ?


Demandez l' opinion de Tom:

L'utilisation d'une instruction dans JDBC doit être localisée à 100% sur DDL (ALTER, CREATE, GRANT, etc.), car ce sont les seuls types d'instructions qui ne peuvent pas accepter les variables BIND.

PreparedStatements ou CallableStatements doivent être utilisés pour TOUS les autres types d'instructions (DML, Queries). Comme ce sont les types d'instruction qui acceptent les variables de liaison.

C'est un fait, une règle, une loi - utilisez des déclarations préparées PARTOUT. Utilisez les déclarations presque pas où.

Il parle spécifiquement d'Oracle mais le même principe s'applique à toute base de données qui met en cache les plans d'exécution.

Des applications de base de données qui adaptent et empêchent les attaques par injection SQL en même temps? Quel est l'inconvénient?


Je voudrais tourner ce tour: dans une application distribuée publiquement, vous devez généralement toujours utiliser des instructions préparées à moins que vous ayez une raison convaincante de ne pas le faire , et vous devez toujours fournir les paramètres "correctement" à l'instruction préparée. chaîne de requête.

Pourquoi? Eh bien, essentiellement à cause des raisons que vous avez données (ou du moins, la deuxième) ...


Outre la prévention de l'injection SQL, la portabilité du formatage (que vous ne pouvez pas obtenir à partir de Statement ), la performance est la raison évidente. Cependant, PreparedStatement ne vient pas sans pénalité. Par exemple, il est généralement plus lent que Statement s'il n'est exécuté qu'une seule fois, car il y a des frais généraux. L'idée générale est que PreparedStatement doit être utilisé lorsque vous effectuez plusieurs fois la même requête. Cependant, le temps nécessaire à la mise en œuvre de PreparedStatement sur Statement , à partir des performances, dépend de votre expérience / expérience réelle d'un serveur de base de données spécifique.


PreparedStatements devrait être utilisé très soigneusement dans les clauses WHERE.

Supposons qu'une table soit définie comme:

create table t (int o, k varchar(100), v varchar(100))

(par exemple "o: ID-objet (clé étrangère), k: clé-attribut, v: valeur-attribut").

En outre, il existe un index (non unique) sur v.

create index ixt on t ( v )

Supposons que cette table contienne 200 millions de lignes insérées comme:

for (i = 0; i < 100*1000*1000; i++) {
  insert into t (o,k,v) values (i,'k1','v1');
  insert into t (o,k,v) values (i,'k2', Convert(i, varchar));
}

("Ainsi, chaque objet o a des attributs k1 = v1 et k2 = o")

Ensuite, vous ne devez pas créer de requêtes comme:

select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k=? and tx.v=? and ty.k=? and ty.v=?

("trouver des objets qui ont deux attributs donnés")

Mon expérience avec ORACLE et MSSQL est que ces requêtes peuvent nécessiter plusieurs minutes pour revenir. Cela est vrai même si aucune ligne ne correspond à la clause where. Cela dépend si le serveur SQL décide de rechercher tx.v ou ty.v en premier.

On devrait mettre les valeurs pour les colonnes k et v directement dans l'énoncé. Je pense que c'est parce que les serveurs SQL prennent en compte les valeurs lors du calcul du plan d'exécution.

Une requête ressemble à ceci renvoie toujours après des millisecondes:

select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k='k1' and tx.v='v1' and ty.k='k2' and ty.v='1234'

("Le serveur SQL recherchera toujours d'abord v = '1234' et ensuite pour v = 'v1'")

Cordialement
Wolfgang


Instruction : Chaque fois que la requête sql est exécutée, cette instruction sql est envoyée au SGBD où elle est compilée. Ainsi, il augmente les charges du serveur et diminue les performances.

connection con=null; 
  String sql="select * from employee where id=5";
Statement st=conn.createStatement();

PreparedStatement : Contrairement à Statement, PreparedStatement reçoit une requête SQL en tant que paramètre lors de sa création.

connection con=null; 
String sql="select * from employee where id=?";
PreparedStatement ps=conn.prepareStatement(sql);

Cette instruction SQL est envoyée à la base de données où elle est compilée. Ainsi, dans prepareStatement, la compilation est effectuée une seule fois, mais dans l'instruction compilée, elle se produit chaque fois que l'instruction est appelée.







prepared-statement