La version 4 de l’API JDBC (Java Database Connectivity) apporte de nombreuses améliorations, notamment en ce qui concerne les pools de connexions, les exceptions et le support de XML.

Cependant, l’utilisation de JDBC n’est pas garante à elle seule de la qualité et de la pérennité d’une solution d’accès aux données. Ainsi, les retours d’expérience issues de la communauté Java ont permis de dégager des bonnes pratiques d’utilisation de L’API JDBC.

Ces bonnes pratiques peuvent être classées selon diverses catégories.

Architecture

Découplage entre la couche métier et la couche d’accès aux données

Séparer la logique métier et la logique d’accès aux données implique de construire une couche distincte pour l’accès et les opérations sur les données (Data Access Layer). Cette couche peut être structurée selon le pattern DAO (Data Access Object).

Cette approche présente deux principaux avantages :

  • elle diminue l’impact d’une modification de l’accès aux données sur le reste des couches de l’application,
  • elle facilite les tests unitaires sur l’accès aux données.

Utilisation d’un framework de persistance

Un framework de persistance offre une abstraction autour de JDBC. Il permet d’établir un pont entre deux représentations distinctes des données : les objets Java de l’application, d’une part, et les tables de la base de donnée, d’autre part.

La mise en œuvre d’un framework de persistance demande certes un effort supplémentaire d’apprentissage et de configuration. Mais une fois assimilé, il peut apporter des avantages indéniables :

  • Gains de qualité de code
    • Réduction de la quantité de code
    • Amélioration de la lisibilité et de l’évolutivité du code
  • Gains de performance
    • Meilleure gestion des ressources, des transactions, et des pool de connexions
    • Gestion plus efficace des batchs

Choix du driver

Utiliser, de préférence, un driver JDBC de type 4. Il s’agit d’un driver écrit en Java utilisant le protocole natif de la base de données. Il est généralement fourni par l’éditeur du SGBD.

Optimisation du code SQL

  • Utiliser l’objet DataSource configuré avec un pool de connexion, de préférence géré par le serveur d’application
  • Utiliser l’objet PreparedStatement correspondant à une requête précompilée. Il est particulièrement adapté à l’exécution répétée d’une même requête avec des paramètres différents.
  • Énumérer l’intégralité des colonnes dans les instructions select et insert
  • Utiliser des objets Date, Time et Timestamp au lieu de String pour récupérer les valeurs temporelles
  • Utiliser la méthode getGeneratedKeys() pour récupérer les clés générées par le SGBD

Gestion des ressources (mémoire et réseau)

Optimiser le paramétrage du pool de connexions

Optimiser le paramétrage du pool de connexions. Sont concernées essentiellement les paramètres suivants :

  • Nombre de connexions (nombre maximal de connexions alloués, nombre maximal de connexions inactives, timeout d’obtention d’une connexion)
  • Activation de la récupération automatique des connexions pour remédier à la fuite éventuelle de connexions (pool leaking)
  • Activation du contrôle automatique de la validité des connexions

Utiliser des mises à jours en lots (batch updates)

Utiliser des mises à jours en lots (batch updates) pour améliorer les performances des traitement effectuant de nombreuses requêtes de mise à jour

Utiliser l’objet RowSet en mode déconnecté

Utiliser l’objet RowSet en mode déconnecté pour charger des données en cache. Ce mécanisme est particulièrement adapté aux données peu dynamiques, comme par exemple des données de paramétrage.

Optimiser l’utilisation de l’objet ResultSet

En cas de récupération d’un grand nombre de lignes à partir de la base, optimiser l’utilisation de l’objet ResultSet :

  • Configurer le chargement des lignes par bloc en utilisant la méthode setFetchSize(int)
  • Pour récupérer la valeur d’un champ, utiliser la méthode getXXX correspondant au type du champ
  • Positionner le mode TYPE_FORWARD_ONLY et le mode CONCUR_READ_ONLY sur l’objet Statement lié
  • Configurer un timeout d’exécution de requête via la méthode setQueryTimeout(int)

Fermer explicitement les objets JDBC

Fermer explicitement les objets JDBC dans un bloc finally. Les objets JDBC doivent être fermés dans la méthode où ils sont utilisés.

Activer le mode ‘lecture seule’

En cas de traitement en lecture seule, activer le mode ‘lecture seule’ en appelant setReadOnly(true) sur la connexion

Vider la pile des points de sauvegarde

Utiliser la méthode releaseSavepoint() de la classe Connection pour vider la pile des points de sauvegarde

Gestion transactionnelle

  • Désactiver le mode auto-commit (configuré par défaut) en appelant setAutoCommit(false) sur l’objet Connection
  • Utiliser le bon niveau d’isolation transactionnel
    • Le niveau d’isolation est fonction des nécessité d’intégrité de la donnée et de la fréquence des accès concurrents.
    • Le choix du niveau d’isolation doit tenir compte des niveaux d’isolation supportés par le driver JDBC et le SGBD.

Portabilité

  • Limiter l’utilisation des instructions spécifiques au SGBD
  • Limiter le recours aux procédures stockées écrites en langage propriétaire

Billets sur le même thème