2
votes

PreparedStatement ne fonctionne pas pour Sybase IQ en Java

Mon équipe et moi avons été confrontés à un problème. Nous essayons de récupérer certaines données de la base de données Sybase IQ et utilisons la clause where pour filtrer et obtenir des données spécifiques.

Le SQL est testé et fonctionne correctement, mais il échoue lors de l'utilisation de Prepared Statement.

/ p>

Tests effectués :

  1. Si nous exécutons la requête (avec ou sans paramètres de clause where), cela fonctionne bien.
  2. Si nous exécutons la requête avec des paramètres codés en dur dans l'instruction préparée, cela fonctionne également très bien.
  3. Si nous définissons les paramètres de l'instruction préparée par programme, cela ne fonctionne pas.

Les tests ci-dessus confirment que la connexion JDBC fonctionne correctement.

La même erreur apparaît lorsque PreparedStatement, JdbcTemplate ou NamedParameterJdbcTemplate est utilisé, donc je soupçonne qu'il pourrait y avoir un problème entre PreparedStatement et Sybase IQ.

Quelqu'un pourrait-il aider à enquêter sur cela? Nous avons trouvé une solution de contournement pour cela, mais il serait vraiment utile de savoir pourquoi cela ne fonctionnait pas.

J'ai trouvé un fil de discussion très similaire ( Comment exécuter PreparedStatement (sélectionnez object_id ()) dans sybase iq? ) sur le même problème, mais personne n'a fourni de réponse acceptée et correcte, j'ai donc décidé de créer une nouvelle question pour cela. P >

Le code utilisé est:

<dependency>
            <groupId>com.sybase</groupId>
            <artifactId>jconn4</artifactId>
            <version>7.0</version>
</dependency>

Le message d'erreur est:

Exception in thread "main" java.sql.SQLException: JZ0SA: Prepared Statement: Input parameter not set, index: 0.
    at com.sybase.jdbc4.jdbc.SybConnection.getAllExceptions(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybStatement.handleSQLE(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybStatement.sendQuery(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybPreparedStatement.sendQuery(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybStatement.executeQuery(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybPreparedStatement.executeQuery(Unknown Source)

Pilote JDBC utilisé (dépendance Maven):

Class.forName("com.sybase.jdbc4.jdbc.SybDriver");

PreparedStatement stmt = con.prepareStatement("select * from myView where off = ? and acc = ?");

stmt.setString(1, "260");
stmt.setString(2, "9050V");
ResultSet set = stmt.executeQuery();


10 commentaires

Veuillez ajouter l'instruction d'exécution.


Bien que les pilotes JDBC doivent utiliser des index basés sur 1 pour les paramètres (requis par la spécification JDBC), avez-vous essayé d'utiliser des index basés sur 0 (car le message d'erreur utilise également un index basé sur 0)? Dans tous les cas, vous devez mettre à jour votre question avec le stacktrace d'exception complet et spécifier la version complète de votre pilote Sybase et de votre serveur Sybase.


Quel pilote JDBC utilisez-vous pour la connexion?


Modifié la question. Oui, j'ai essayé d'utiliser des index basés sur 0 - ArrayOutOfBoundsException a été levée, donc un index basé sur 1 doit absolument être utilisé.


À partir du code que vous avez publié: sélectionnez * dans la vue où désactivé =? et acc =? . La vue est-elle une table de base de données? Quel est le type de données off et acc ?


avez-vous essayé d'utiliser les pilotes jConnect, iAnywhere, jTDS ou jdbc: sqlserver?


@Abra view représente la vue de la base de données. Les types de données off et acc sont char (3) et char (5). J'ai essayé d'utiliser char [] au lieu de String dans le code Java pour les paramètres, mais cela n'a pas aidé.


@DrPhil Nous utilisons jConnect. Veuillez vérifier le message modifié.


Parfois, select * peut causer des problèmes dans JDBC. Avez-vous essayé de remplacer * par la liste des noms des colonnes de la vue ?


@Abra J'ai essayé de sélectionner une colonne au lieu de select *, toujours la même erreur.


3 Réponses :


0
votes

stmt.setString (1, "260"); stmt.setString (2, "9050V");

L'index du tableau commence par 0 non? n'est-ce pas une indexation de base zéro dans votre API utilisée?


2 commentaires

Selon la documentation Java, les index PreparedStatement commencent à 1 - voir docs.oracle.com/javase/7/docs/api/java/sql/...


Est-ce une réponse? Cela devrait-il plutôt être un commentaire?



1
votes

J'ai rencontré le même problème avec sybase iq. J'ai ajouté les deux lignes de code suivantes pour résoudre le problème, avant l'instruction prepareStatement.execureQuery () .

 preparedStatement.setFetchSize(Integer.MAX_VALUE);
 preparedStatement.setFetchDirection(ResultSet.FETCH_FORWARD);

Je ne sais pas si c'est la bonne chose à faire mais cela a fonctionné.

OU

vous pouvez définir prepareStatement.setCursorName ("SomeCursorName"); cela a également résolu le problème. Mais dans le cas d'un environnement multi-thread, vous devez définir un nom de curseur unique. Peut-être utiliser un nombre aléatoire ou quelque chose et ne pas créer trop de curseurs, les limiter au nombre de threads simultanés qui seraient exécutés en même temps.


0 commentaires

0
votes

J'ai utilisé la propriété de connexion jconn4 LITERAL_PARAMS = true et cela a bien fonctionné. Attention, les performances devraient être affectées.

Lorsqu'il est défini sur «true», tous les paramètres définis par les méthodes setXXX dans l'interface PreparedStatement sont insérés littéralement dans l'instruction SQL lors de son exécution. Si la valeur est «false», les marqueurs de paramètre sont laissés dans l'instruction SQL et les valeurs des paramètres sont envoyées au serveur séparément.


0 commentaires