Nous avons un système par lequel la connexion à la base de données est établie une fois en utilisant une méthode commune et est transmise dans la classe appropriée à utiliser. Il y a des doutes que le passage de la connexion à la base de données en tant que paramètre à différentes classes causerait un problème, donc je vérifie ici pour voir si cela est réellement viable, et y a-t-il de meilleurs modèles pour le faire?
Je sais qu'il existe des outils ORM pour faire de la persistance, mais nous ne pouvons pas y aller pour l'instant ..
Toute rétroaction est la bienvenue, merci.
java
database
patterns-and-practices
ipohfly
la source
la source
Réponses:
Oui, il est possible de contourner une connexion. Vous gérez la connexion dans un bloc de contrôle externe. Il n'y a rien de dangereux à cela.
Ce qui n'est pas sûr, c'est d'écrire du code qui ne garantit pas que la connexion est correctement éliminée en temps opportun. Oublier de nettoyer une ressource n'est pas lié à sa transmission. Vous pouvez tout aussi facilement écrire du code qui laisse une connexion suspendue sans la faire passer n'importe où.
En C ++, vous êtes protégé par RAII si vous allouez sur la pile ou utilisez des pointeurs intelligents. En C #, établissez une règle stricte selon laquelle tous les objets jetables (tels que les connexions) doivent être déclarés dans un bloc "using". En Java, nettoyez avec la logique try-finally. Ayez des revues de code sur tout le code de la couche de données pour vous en assurer.
Le cas d'utilisation le plus courant est lorsque vous avez plusieurs opérations qui peuvent être combinées dans de nombreuses permutations. Et chacune de ces permutations doit être une transaction atomique (toutes réussissent ou annulent). vous devez ensuite transmettre la transaction (et donc la connexion correspondante) à toutes les méthodes.
Supposons que nous ayons de nombreuses actions foobar () qui peuvent être combinées de diverses manières en tant que transactions atomiques.
BTW, vous voudrez ouvrir les connexions le plus tard possible, les éliminer dès que possible. Vos coéquipiers pourraient avoir raison si vous traitez les connexions en tant que membres d'objet, en les présentant comme un état inutile et en laissant les connexions ouvertes beaucoup plus longtemps que nécessaire. Mais l'acte de passer une connexion ou une transaction en tant que paramètre n'est pas intrinsèquement mauvais.
BTW. Selon la prise en charge de votre langue pour les fonctions de première classe, vous pouvez effectuer une liste d'actions foobar (). Une seule fonction peut donc gérer toutes les permutations des actions. Élimination de la duplication du bloc de contrôle externe pour chaque permutation.
la source
Il semble que vous soyez après l' injection de dépendance . Autrement dit, la connexion groupée est créée une fois et injectée partout où cela est nécessaire. La connexion via un paramètre de méthode est certainement une façon d'injecter des dépendances, mais un conteneur IoC tel que Guice, PicoContainer ou Spring est une autre manière (plus sûre) de le faire.
L'utilisation de DI signifie que vous pouvez parfaitement résumer la logique autour de la création, de l'ouverture, de l'utilisation et de la fermeture de la connexion, loin de votre logique métier principale.
Spring JDBC et al sont d'autres exemples de ce type de comportement pour vous
la source
Le fait de contourner des éléments de base de données plutôt que des éléments de données peut entraîner des problèmes. Dans cette mesure, chaque fois que cela est possible, ne passez pas une chose de base de données à moins que l'on puisse garantir une bonne hygiène de la base de données.
Le problème avec la transmission des éléments de la base de données est qu'elle peut être bâclée. J'ai vu plus d'un bogue dans le code avec quelqu'un passant autour d'une connexion à la base de données, que quelqu'un saisit ensuite un jeu de résultats et se cache dans un objet local (le jeu de résultats, toujours connecté à la base de données), puis attache un curseur dans le base de données pendant un temps significatif. Une autre instance, quelqu'un a passé un jeu de résultats à quelqu'un d'autre (qui a ensuite été caché), puis la méthode qui a passé le jeu de résultats l'a fermé (et l'instruction), ce qui a entraîné des erreurs lorsque d'autres méthodes ont essayé de travailler avec le jeu de résultats qui ne l'était plus.
Tout cela découle du non-respect de la base de données, de la connexion, de l'instruction, du jeu de résultats et de leur cycle de vie.
Pour éviter cela, il existe des modèles et des structures qui fonctionnent mieux avec les bases de données et qui n'ont pas besoin de bases de données pour sortir des classes dans lesquelles ils sont confinés. Les données entrent, les données sortent, la base de données reste en place.
la source
Root
un Dao. Mais alors vous réalisez que vous voulez également un moyen d'obtenir unNode
sans retirer tout l'Root
objet avec. Comment faites-vous pour que leRoot
Dao appelle leNode
code Dao (c'est-à-dire: réutilisation), mais assurez-vous que leNode
Dao ne ferme la connexion que lorsque leNode
Dao est directement appelé et maintient la connexion ouverte lorsque leRoot
Dao est appelé?La transmission d'
Connection
instances n'est généralement pas un problème, même si dans la plupart des situations, seules les implémentations DAO devraient avoir quelque chose à voir avec elles. Maintenant, votre problème étant que les connexions ne sont pas fermées après utilisation, il est en fait facile à résoudre: l'Connection
objet doit être fermé au même niveau qu'il est ouvert, c'est-à-dire dans la même méthode. J'utilise personnellement le modèle de code suivant:De cette façon, je m'assure que toutes les connexions sont toujours fermées, même si une exception est levée dans le bloc. En fait, je vais aussi longtemps que j'utilise exactement le même modèle pour
Statement
et lesResultSet
instances, et tout s'est bien déroulé jusqu'à présent.Edit 2018-03-29: Comme indiqué par user1156544 dans les commentaires ci-dessous, à partir de Java 7, l'utilisation de la construction try-with-resources doit être privilégiée. En l'utilisant, le modèle de code que j'ai fourni dans ma réponse initiale peut être simplifié comme suit:
la source
dataSource
plutôt queDataSource
(je vais corriger ma réponse concernant ce point). Le type exact de cet objet seraitjavax.sql.DataSource
. Dans l'ancien code, j'avais l'habitude d'avoir un singleton pour gérer toutes les sources de données disponibles dans mes applications. Mes DAO n'avaient pas besoin de le savoir, car l'DataSource
instance est fournie via l'injection de dépendance.il y a un compromis à faire les choses de cette façon plutôt que d'utiliser un singleton que vous pouvez obtenir au besoin. J'ai fait les choses dans les deux sens dans le passé.
En général, vous devez réfléchir aux conséquences de la gestion de la connexion à la base de données, et cela peut être orthogonal ou non à l'utilisation des requêtes de base de données. Par exemple, si vous avez une connexion db pour une instance d'application donnée et qu'elle se ferme lorsqu'elle n'est pas utilisée, ce serait orthogonal. Mettez la gestion dans une classe singleton et ne la passez pas. Cela vous permet de gérer la connexion db selon vos besoins. Par exemple, si vous souhaitez fermer une connexion à chaque validation (et la rouvrir lors du prochain appel), cela est plus facile à faire sur un singleton car l'API pour cela peut être centralisée.
Par contre, supposons que vous ayez besoin de gérer un pool de connexions où un appel donné peut avoir besoin d'utiliser n'importe quelle connexion arbitraire. Cela peut se produire lors de l'exécution de transactions distribuées sur plusieurs serveurs, par exemple. Dans ce cas, il vaut généralement mieux passer l'objet de connexion db que vous ne travaillez avec des singletons. Je pense que c'est généralement le cas le plus rare, mais il n'y a rien de mal à le faire quand vous en avez besoin.
la source