web-dev-qa-db-fra.com

Hibernate: hbm2ddl.auto = mise à jour en production?

Puis-je exécuter des applications Hibernate configurées avec hbm2ddl.auto=update pour mettre à jour le schéma de base de données dans un environnement de production?

317
cretzel

Non, c'est dangereux.

Malgré tous les efforts de l’équipe Hibernate, vous ne pouvez tout simplement pas compter sur des mises à jour automatiques en production. Écrivez vos propres correctifs, passez-les en revue avec DBA, testez-les, puis appliquez-les manuellement.

Théoriquement, si mise à jour de hbm2ddl a fonctionné en développement, il devrait également fonctionner en production. Mais en réalité, ce n'est pas toujours le cas.

Même si cela a fonctionné correctement, cela peut être sous-optimal. Les DBA sont payés autant pour une raison.

368
Vladimir Dyuzhev

Nous le faisons en production, mais avec une application qui n’est pas critique et sans aucun administrateur de base hautement rémunéré. Il s’agit là d’un processus manuel de moins sujet aux erreurs humaines: l’application peut détecter la différence et faire le bon choix, sans compter que vous l’avez probablement testée dans divers environnements de développement et de test.

Une mise en garde - dans un environnement en cluster, vous voudrez peut-être l'éviter car plusieurs applications peuvent apparaître simultanément et essayer de modifier le schéma, ce qui pourrait être mauvais. Vous pouvez également mettre en place un mécanisme dans lequel une seule instance est autorisée à mettre à jour le schéma.

70
Brian Deterling

Les créateurs d'Hibernate déconseillent de le faire dans un environnement de production de leur livre "Java Persistence with Hibernate" :

AVERTISSEMENT: des utilisateurs d'Hibernate ont essayé d'utiliser SchemaUpdate pour mettre à jour automatiquement le schéma d'une base de données de production. Cela peut rapidement se terminer en catastrophe et ne sera pas autorisé par votre administrateur de base de données.

51
Roman

Consultez LiquiBase XML pour conserver un journal des mises à jour. Je ne l'avais jamais utilisé jusqu'à cette année, mais j'ai découvert qu'il était très facile à apprendre et à rendre le contrôle de révision/migration/gestion de révision de base de données très fiable. Je travaille sur un projet Groovy/Grails, et Grails utilise Hibernate pour tous ses ORM (appelés "GORM"). Nous utilisons Liquibase pour gérer tous les changements de schéma SQL, ce que nous faisons assez souvent à mesure que notre application évolue avec de nouvelles fonctionnalités.

Fondamentalement, vous conservez un fichier XML de jeux de modifications que vous continuez d'ajouter à mesure que votre application évolue. Ce fichier est conservé dans git (ou ce que vous utilisez) avec le reste de votre projet. Lorsque votre application est déployée, Liquibase vérifie sa table de journal des modifications dans la base de données à laquelle vous vous connectez afin de savoir ce qui a déjà été appliqué. Elle applique ensuite de manière intelligente les modifications qui n'ont pas encore été appliquées à partir du fichier. Cela fonctionne parfaitement dans la pratique, et si vous l’utilisez pour toutes vos modifications de schéma, vous pouvez être sûr à 100% que le code que vous extrayez et déployez sera toujours capable de se connecter à un schéma de base de données entièrement compatible.

Ce qui est génial, c’est que je puisse prendre une base de données mysql totalement vierge sur mon ordinateur portable, lancer l’application, et tout de suite le schéma est configuré pour moi. Cela facilite également le test des modifications de schéma en les appliquant d’abord à une base de développement ou à une base de données intermédiaire.

Le moyen le plus simple de démarrer avec ce logiciel serait probablement d'utiliser votre base de données existante, puis d'utiliser Liquibase pour générer un fichier initial baseline.xml. Dans le futur, vous pourrez simplement l’annexer et laisser liquibase prendre en charge la gestion des modifications de schéma.

http://www.liquibase.org/

28
jpswain

Hibernate doit mettre en garde de ne pas utiliser les mises à jour automatiques dans prod pour se couvrir lorsque des personnes ne sachant pas ce qu’elles font l’utilisent dans des situations où elles ne devraient pas être utilisées.

Les situations dans lesquelles il ne devrait pas être utilisé sont nettement plus nombreuses que celles où il est acceptable.

Je l'utilise depuis des années sur de nombreux projets et je n'ai jamais eu un seul problème. Ce n'est pas une réponse boiteuse, et ce n'est pas un code de cow-boy. C'est un fait historique.

Une personne qui dit "ne le faites jamais en production" songe à un ensemble spécifique de déploiements de production, à savoir ceux avec lesquels il est familier (sa société, son secteur, etc.).

L'univers des "déploiements de production" est vaste et varié.

Un développeur Hibernate expérimenté sait exactement quel type de DDL va résulter d’une configuration de mappage donnée. Tant que vous testez et validez que ce que vous attendez aboutit au DDL (dev, qa, staging, etc.), tout va bien.

Lorsque vous ajoutez de nombreuses fonctionnalités, les mises à jour automatiques des schémas peuvent vous faire gagner du temps.

La liste des choses que les mises à jour automatiques ne gèrent pas est sans fin, mais quelques exemples sont la migration de données, l'ajout de colonnes non nullables, les changements de noms de colonnes, etc., etc.

Vous devez également faire attention dans les environnements en cluster.

Mais encore une fois, si vous saviez tout cela, vous ne poseriez pas cette question. Hmm. . . OK, si vous posez cette question, attendez de nombreuses expériences avec Hibernate et les mises à jour automatiques de schémas avant de penser à l’utiliser dans prod.

25
john.stein

Je voterais non. Hibernate ne semble pas comprendre quand les types de données des colonnes ont changé. Exemples (utilisant MySQL):

String with @Column(length=50)  ==> varchar(50)
changed to
String with @Column(length=100) ==> still varchar(50), not changed to varchar(100)

@Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed

Il y a probablement d'autres exemples, tels que pousser la longueur d'une colonne String jusqu'à 255 et la voir convertir en texte, texte moyen, etc.

Certes, je ne pense pas qu’il existe vraiment un moyen de "convertir des types de données" sans créer une nouvelle colonne, copier les données et détruire l’ancienne colonne. Mais à la minute où votre base de données contient des colonnes ne reflétant pas la cartographie Hibernate actuelle, vous vivez de manière très dangereuse ...

Flyway est une bonne option pour traiter ce problème:

http://flywaydb.org

24
cliff.meyers

Comme je l'ai expliqué dans cet article , utiliser hbm2ddl.auto en production n'est pas une bonne idée.

Le seul moyen de gérer le schéma de base de données consiste à utiliser des scripts de migration incrémentiels pour les raisons suivantes:

  • les scripts résideront dans VCS avec votre base de code. Lorsque vous extrayez une branche, vous recréez l'intégralité du schéma.
  • les scripts incrémentiels peuvent être testés sur un serveur d'assurance qualité avant d'être appliqués en production
  • aucune intervention manuelle n'est nécessaire car les scripts peuvent être exécutés par Flyway , ce qui réduit donc le risque d'erreur humaine associée à l'exécution manuelle de scripts.

Même le Guide de l'utilisateur Hibernate vous conseille d'éviter d'utiliser l'outil hbm2ddl pour les environnements de production.

enter image description here

14
Vlad Mihalcea

Nous le faisons dans un projet en production depuis des mois et n’avons jamais eu de problème à ce jour. Gardez à l'esprit les 2 ingrédients nécessaires à cette recette:

  1. Concevez votre modèle d'objet avec une approche de compatibilité ascendante, c'est-à-dire obsolète objets et attributs plutôt que de les supprimer/modifier. Cela signifie que si vous devez modifier le nom d'un objet ou d'un attribut, laissez l'ancien, maintenez-le tel quel, ajoutez-en un nouveau et écrivez un type de script de migration. Si vous devez modifier une association entre des objets, si vous êtes déjà en production, cela signifie en premier lieu que votre conception était fausse. Essayez donc de penser à une nouvelle façon d'exprimer la nouvelle relation, sans affecter les anciennes données.

  2. Toujours sauvegarde la base de données avant le déploiement.

Mon sentiment est - après avoir lu cet article - que 90% des participants à cette discussion sont horrifiés par l'idée d'utiliser de telles automatisations dans un environnement de production. Certains lancent le ballon vers le DBA. Prenez un moment pour considérer que tous les environnements de production ne fournissent pas un administrateur de base de données et que peu d’équipes de développement sont en mesure d’en acheter un (du moins pour les projets de taille moyenne). Donc, si nous parlons d’équipes où tout le monde doit tout faire, la balle est sur elles.

Dans ce cas, pourquoi ne pas simplement essayer d’avoir le meilleur des deux mondes? Des outils comme celui-ci sont là pour vous aider, ce qui - avec une conception et un plan soignés - peut aider dans de nombreuses situations. Et croyez-moi, les administrateurs risquent d’être difficiles à convaincre au départ, mais s’ils savent que le ballon n’est pas sur leurs mains, ils vont adorer.

Personnellement, je ne recommencerais jamais à écrire des scripts à la main pour étendre n'importe quel type de schéma, mais c'est juste mon opinion. Et après avoir commencé récemment à adopter des bases de données sans schéma NoSQL, je peux voir que, très bientôt, toutes ces opérations basées sur des schémas appartiendront au passé. Vous feriez donc mieux de changer de perspective et de regarder vers l'avenir.

7
chris

Je ne le risquerais pas car vous risqueriez de perdre des données qui auraient dû être préservées. hbm2ddl.auto = update est un moyen simple de garder votre base de données dev à jour.

7
Jaap Coomans
  • Dans mon cas (Hibernate 3.5.2, Postgresql, Ubuntu), la définition de hibernate.hbm2ddl.auto=update ne créait que de nouvelles tables et créait de nouvelles colonnes dans des tables déjà existantes.

  • Il n'a ni supprimé de tables, ni de colonnes, ni modifié de colonnes. Cela peut être appelé une option sûre, mais quelque chose comme hibernate.hbm2ddl.auto=create_tables add_columns serait plus clair.

6
user1027272

Ce n'est pas sûr, pas recommandé, mais c'est possible.

J'ai de l'expérience dans une application utilisant l'option de mise à jour automatique en production.

Eh bien, les principaux problèmes et risques rencontrés dans cette solution sont les suivants:

  • déployer dans la mauvaise base de données. Si vous commettez l’erreur d’exécuter le serveur d’application avec une ancienne version de l’application (EAR/WAR/etc) dans une base de données incorrecte, vous aurez beaucoup de nouvelles colonnes, tables, clés étrangères et erreurs. Le même problème peut survenir avec une simple erreur dans le fichier de source de données (copier/coller le fichier et avoir oublié de modifier la base de données). En résumé, la situation peut être un désastre dans votre base de données.
  • Le serveur d'application prend trop de temps à démarrer. Cela se produit car Hibernate essaie de trouver toutes les tables/colonnes/etc créées à chaque démarrage de l'application. Il a besoin de savoir ce qui doit être créé (table, colonne, etc.). Ce problème ne fera qu'empirer avec la croissance des tables de la base de données.
  • outils de base de données, il est presque impossible à utiliser. Pour créer des scripts de base de données à exécuter avec une nouvelle version, vous devez penser à ce qui sera créé par la mise à jour automatique après le démarrage du serveur d'applications. Par exemple, si vous devez remplir une nouvelle colonne avec des données, vous devez démarrer le serveur d'applications, attendez qu'Hibernate crée la nouvelle colonne et n'exécutez le script SQL qu'après. Comme vous pouvez le constater, les outils de migration de base de données (tels que Flyway, Liquibase, etc.) sont quasiment impossibles à utiliser avec la mise à jour automatique activée.
  • Les modifications de la base de données ne sont pas centralisées. Avec la possibilité qu'Hibernate crée les tables et tout le reste, il est difficile de surveiller les modifications apportées à la base de données dans chaque version de l'application, car la plupart d'entre elles le sont automatiquement.
  • Encourage les ordures sur la base de données. En raison de la facilité de mise à jour automatique, il est possible que votre équipe néglige de supprimer les anciennes colonnes et les anciens tableaux.
  • catastrophe imminente. Le risque imminent qu'une catastrophe se produise dans la production (comme certaines personnes mentionnées dans d'autres réponses). Même avec une application en cours d'exécution et pouvant être mise à jour pendant des années, je ne pense pas qu'elle soit sûre. Je ne me suis jamais senti en sécurité avec cette option.

Donc, je ne recommanderai pas d'utiliser la mise à jour automatique en production.

Si vous voulez vraiment utiliser la mise à jour automatique en production, je vous recommande:

  • Réseaux séparés. Votre environnement de test ne peut pas accéder à l'environnement des homologues. Cela permet d'éviter qu'un déploiement supposé être dans l'environnement de test modifie la base de données d'homologation.
  • Gérer l'ordre des scripts. Vous devez organiser vos scripts pour qu'ils s'exécutent avant votre déploiement (modification de table de structure, suppression de table/colonnes) et votre script après le déploiement (informations de remplissage pour les nouvelles colonnes/tables).

Et, différent des autres posts, je ne pense pas que la mise à jour automatique permette sa relation avec des DBA "très bien payés" (comme mentionné dans d'autres posts) ... Les DBA ont des choses plus importantes à faire que d'écrire des instructions SQL pour créer/change/delete tables et colonnes. Ces tâches simples peuvent être effectuées et automatisées par les développeurs. Elles ne sont transmises qu’à l’équipe DBA, qui n’a pas besoin d’Hibernate et des DBA "très bien payés" pour les écrire.

5
Dherik

Non, ne le fais jamais. Hibernate ne gère pas la migration de données. Oui, cela donnera à votre schéma une apparence correcte, mais cela ne garantit pas que des données de production précieuses ne sont pas perdues au cours du processus.

4
Robert
  • Généralement, les applications d'entreprise des grandes entreprises fonctionnent avec des privilèges réduits.

  • Le nom d'utilisateur de la base de données peut ne pas avoir le privilège DDL pour ajouter les colonnes nécessaires à hbm2ddl.auto=update.

4
Rajeev Goel

Je suis d'accord avec Vladimir. Les administrateurs de mon entreprise n’apprécieraient certainement pas si je proposais un tel cours.

De plus, créer un script SQL au lieu de faire confiance à Hibernate vous donne l’opportunité de supprimer des champs qui ne sont plus utilisés. Hibernate ne fait pas ça.

Et je trouve que la comparaison du schéma de production avec le nouveau schéma vous donne une idée encore plus précise de ce que vous avez modifié dans le modèle de données. Vous savez, bien sûr, parce que vous l'avez fait, mais maintenant, vous voyez tous les changements en une fois. Même ceux qui vous font aller comme "c'est quoi ce bordel?!".

Il existe des outils qui peuvent créer un delta de schéma pour vous, donc ce n'est pas même un travail difficile. Et puis vous savez exactement ce qui va se passer.

2
extraneon

Le schéma des applications peut évoluer dans le temps; Si vous avez plusieurs installations, qui peuvent avoir différentes versions, vous devriez pouvoir vous assurer que votre application, un outil ou un script est capable de migrer le schéma et les données d’une version à l’autre.

Avoir toute votre persistance dans les mappages (ou annotations) d'Hibernate est un très bon moyen de contrôler l'évolution du schéma.

Vous devez considérer que l'évolution du schéma doit prendre en compte plusieurs aspects:

  1. évolution du schéma de base de données en ajoutant plus de colonnes et de tables

  2. suppression d'anciennes colonnes, tables et relations

  3. remplir de nouvelles colonnes avec des valeurs par défaut

Les outils Hibernate sont importants, en particulier dans le cas (comme dans mon cas), vous avez différentes versions de la même application sur de nombreux types de bases de données.

Le point 3 est très sensible au cas où vous utiliseriez Hibernate, comme si vous introduisiez une nouvelle propriété de valeur booléenne ou numérique, si Hibernate trouverait une valeur nulle dans de telles colonnes, si une exception serait levée.

Donc, ce que je ferais, c’est utiliser la capacité de mise à jour de schéma d’Hibernate Tools, mais vous devez également ajouter un rappel de maintenance des données et du schéma, comme pour le remplissage des valeurs par défaut, la suppression des colonnes non utilisées, etc. De cette manière, vous bénéficiez d'avantages (scripts de mise à jour de schéma indépendants de la base de données et évitant le codage en double des mises à jour, en permanence et en scripts), mais vous couvrez également tous les aspects de l'opération.

Ainsi, par exemple, si une mise à jour de version consiste simplement à ajouter une propriété à valeur varchar (donc une colonne), dont la valeur par défaut peut être null, la mise à jour automatique étant terminée. Là où plus de complexité est nécessaire, plus de travail sera nécessaire.

Cela suppose que l'application mise à jour soit capable de mettre à jour son schéma (cela peut être fait), ce qui signifie également qu'elle doit disposer des droits d'utilisateur pour le faire sur le schéma. Si la politique du client l'empêche (cas probable du cas Lizard Brain), vous devrez fournir les scripts spécifiques à la base de données.

2
Pietro Polsinelli