La persistance est un des sujets les plus discutés dans le monde de Java EE, et pour cause. En entreprise, les données sont la possession le plus précieuse de la société, et les logiciels informatiques qui gèrent et touchent à ces données sont donc très sensibles. Pourtant, ce n'est pas toujours facile de s'y retrouver en Java, surtout suite à la propagation des solutions de persistance qui ont été publiés depuis l'échec des Entity Beans dans l'ancienne version d'EJB. Je fais ici un petit survol de la situation actuelle des solutions pour la persistance en Java; ce n'est pas un traitement complet du sujet, mais j'espère au moins aider le lecteur qui s'y connaît un peu de se retrouver un peu mieux dans ce domaine.
D'abord, il faut absolument distinguer deux types de persistance: la persistance d'objet et la modélisation relationnelle des données. La persistance d'objet est le plus simple d'un point de vue d'un programmeur débutant. On a des objets, en on voudrait les garder pour les récupérer plus tard. Même si ce type de persistance est très simple, il ne faut pas oublier que dans certains cas, il est suffisant.
Cependant dans d'autre circonstances (notamment les circonstances rencontrées presque toujours en entreprise), la persistance d'objet ne suffit pas. Et ce notamment parce que les données ne sont pas la propriété d'un seul logiciel ou même d'un seul plateforme, mais elles appartiennent à toute la société. Lorsque quelque chose est saisie dans une application, les autres applications vont vouloir en tenir compte elles aussi.
Dans une telle situation, la persistance d'objet direct devient rapidement un bazar ingérable. Le modèle relationnel nous sort de cette impasse. Il fournit une façon mathématiquement formelle de décrire et modeler nos données. Les bases de données SQL telles DB2, Oracle, et SQL Server permettent de stocker des données de façon relationnelle. Elles fournissent en plus d'autres fonctionnalités importantes pour l'entreprise, notamment la gestion de l'intégrité transactionnelle et des back-ups. Le programmeur Java EE se doit de bien comprendre l'intérêt et le fonctionnement des bases de données relationnelles, et de la normalisation. C'est vraiment une connaissance indispensable dans ce métier.
Un problème intervient, pourtant, lorsqu'on veut utiliser une base de données relationnelle avec un programme Java, car en Java on travaille avec les objets discrets, et non pas les tuples et les relations. Le problème du mapping objet-relationnel ou ORM, décrit le processus par lequel on traduit nos structures de données entre ces deux mondes conceptuels différents.
Maintenant qu'on a définit les deux types de persistance, on peut regarder les solutions qui existent en Java.
I. Si la persistance d'objet nous suffit, ce qui est généralement le cas lorsqu'on veut juste sauvegarder les données pour son application, sans nécessairement devoir les communiquer avec d'autres systèmes, deux solutions sont possibles.
1. La façon la plus directe de faire cela en Java c'est en implémentant java.io.Serializable. Le désavantage c'est que les fichiers .ser sont vraiment particuliers à Java, et ne peuvent pas être exportés vers un autre système. Aussi, la persistance n'est pas centralisée. Enfin, on ne peut pas rechercher dans les objets stockés sans les charger tous préalablement, ce qui dans beaucoup de situations n'est simplement pas réaliste.
Serializable n'est donc une solution que pour les applications avec les besoins de persistance les plus simples.
2. On peut opter pour JDO, un framework qui fait partie du Java standard (qui réside dans le package javax.jdo) et qui existe en plusieurs implémentations matures. (Si vous débutez dans le JDO, je conseille d'essayer l'implémentation gratuite, JPOX.) JDO travaille avec les objets en tant qu'objets (à la différence des solutions ORM ici-bas), mais peut tout de même se servir d'une base de données pour stocker ses informations. (D'autres formes de stockage, comme l'XML, sont aussi possibles.) Un système basé sur JDO peut commencer très simplement et devenir peu à peu très large et très complexe, ce qui est un fort avantage. Puissant et facile d'utilisation, JDO peut être la solution optimale dans beaucoup de cas. Pourtant, en prenant l'objet et non pas le modèle relationnel comme sa base de fonctionnement, avec JDO on sacrifie le sûreté que seul une base de données relationnelle normalisée peut fournir. (Ou bien, on fait un effort supplémentaire pour assurer que les données sont normalisées dans la base, mais JDO ne nous aide pas beaucoup dans cette démarche.)
II. Si une base de données relationnelle nous est nécessaire, il y a trois choix principaux qui semblent avoir un avenir.
1. On peut opter pour la JDBC. Avec cette solution, on prend en charge le mapping object-relationnel nous-mêmes. On a l'avantage de contrôler toutes nos requêtes, mais on est obligé de coder beaucoup plus aussi. Un avantage, en plus du contrôle, c'est qu'il suffit de connaître Java et SQL pour s'y mettre, plutôt que d'apprendre un nouveau framework. Mais en échange, on est obligé de coder beaucoup plus de code répétitif, juste pour pouvoir constituer nos objets. Souvent on découvre qu'on passe plus de temps à coder de la plomberie JDBC qu'à coder la partie métier de notre application!
2. On peut adopter le plus populaire des frameworks ORM, Hibernate. Avec Hibernate, on définit le mapping objet-relationnel dans des fichiers XML, et évite ainsi de dupliquer le travail en écrivant des requêtes à droite et à gauche (avec la possibilité d'erreurs que cela entraîne). Très populaire et open source, on retrouve facilement des conseilles et des outils pour travailler avec Hibernate sur internet. Pourtant, à la différence de JDO et JPA, Hibernate ne fait pas partie du Java standard, et JBoss est la seule société à le supporter commercialement.
3. On peut opter pour le nouveau standard, sorti avec le nouvel EJB 3.0, la JPA (Java Persistence API) (qui réside dans le package javax.persistence). JPA ressemble à Hibernate, mais au lieu de gérer un fichier XML pour chaque classe qu'on veut persister, on peut se servir des annotations directement sur la classe pour indiquer sa correspondance sur la base de données. Se servant ainsi de Java 5, en pratique JPA est beaucoup plus facile à gérer, et il a l'appui de tous les vendeurs du monde Java (Sun, Oracle, BEA, JBoss, Apache, etc.). Les désavantages principaux sont le fait qu'il faut utiliser la version Java 5 ou supérieur, et que JPA est plus jeune que les autres solutions mentionnés ici, qui ont tous eu plus de temps pour faire leurs preuves.
Voilà, c'est un survol des solutions principales de persistance. Evidemment le sujet est grand et je n'ai pas la place ou le temps d'expliquer chaque solution en profondeur. Mais souvent la première question qu'on a, c'est "par où commencer", alors j'espère que maintenant le lecteur pourra cerner lui-même si c'est une solution objet ou ORM qu'il faut, et ensuite laquelle correspond le mieux aux besoins présentes. Si le modèle relationnel n'a pas un intérêt central, JDO peut offrir le meilleur compromis entre puissance et simplicité. Mais dans le plupart des cas, le nouveau standard JPA sera le plus fréquemment le meilleur choix. Pourtant, si votre projet et dans Java 1.4, ou si vous avez déjà des programmeurs qui le connaissent sur le projet, vous opteriez plutôt pour Hibernate.
Et pour ceux qui préfèrent continuer à coder en JDBC à la main, pensez à migrer vers Java 6—cette version la plus récente de Java revoit et simplifie le JDBC pour le plus grand bonheur des programmeurs!