Qu'est-ce que la piscine hikari??
Cette simple question dans un post sur BlueSky m'a amené à une explication que j'ai trouvée vraiment cool. Je suis venu ici pour le terminer.
Dans le contexte précis, on parlait de Hikari Connection Pool. Mais si Hikari est un pool de connexions, que serait un ??pool????
Tout d’abord, le concept de piscine
Avant d'expliquer ce qu'est HikariCP, nous devons expliquer ce qu'est un pool de connexions. Et pour expliquer le pool de connexions, nous devons expliquer le pool.
Devrions-nous utiliser une analogie économique pour cela?? Une analogie économique historique pleine de défauts et d’inexactitudes avec le monde réel, mais allez, suspendez vite votre incrédulité juste pour l’explication ! Il est autonome.
Imaginez que vous êtes un seigneur/une dame à l'époque médiévale. Vous détenez les outils pour effectuer le travail des paysans. Et vous voulez qu'ils fonctionnent. Alors comment garantir cela ? Si les outils sont les v?tres ? Il vous faudra livrer les outils aux paysans, simple.
Alors imaginez la situation : votre paysan a besoin d'une houe pour désherber la terre, alors il s'y rend et vous demande une houe. Vous lui donnerez la houe et vous vivrez. Mais s'il ne le rend pas, qu'en est-il de son stock de putes ? Un jour, ?a finira...
Une alternative à la remise de la houe est de faire fabriquer une houe. Vous êtes le seigneur/dame de ces terres, vous avez donc accès au forgeron pour fondre le métal en forme de houe et le mettre dans un manche. Mais ce n’est pas quelque chose que l’on peut produire immédiatement sans que le paysan soit assis dans une salle d’attente. Pour créer cette nouvelle fonctionnalité, vous avez besoin d'une énorme quantité de temps et d'énergie.
Désormais, si le paysan rend la houe à la fin de la journée, elle devient disponible pour qu'un autre paysan puisse l'utiliser le lendemain.
Ici, vous contr?lez le pool de putes. Le pool est un modèle de conception qui indique que vous pouvez effectuer les actions suivantes?:
- demandez-lui un élément
- retourner l'élément
Autres éléments courants à avoir dans les pools d'objets?:
- possibilité de créer plus d'objets, à la demande, en les enregistrant dans le pool
- possibilité de détruire des objets du pool (ou de le dissocier de ce pool)
Connexion à la base de données JDBC
Eh bien, rapprochons-nous de HikariCP. Parlons ici des connexions aux bases de données en Java.
En java, on demande d'établir une connexion à la base de données. Il existe l'option de connexion directe, dont vous avez besoin pour comprendre directement quelles classes appeler et certains détails, ou bien simplement profiter de l'option de découverte de service.
A priori, pour utiliser la découverte de services, le fournisseur de services fait un moyen d'enregistrer ce qu'il fournit, puis la ? découverte de services ? le suit pour voir qui pourrait répondre à cette demande.
Un cas de découverte de service?: pstmt-null-safe
J'ai eu un cas où je devais établir des connexions JDBC pour parler à la base de données. Cependant, mon pilote JDBC n'acceptait pas l'utilisation de valeurs nulles comme valeurs, uniquement des valeurs nulles directement dans les requêtes. Alors qu'est-ce que j'ai fait ? Un chauffeur au dessus d'un chauffeur !
L'idée générale était la suivante. Imaginez que j'ai cette requête dans laquelle je souhaite insérer des valeurs?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?)
Imaginez maintenant que je m'occupe de la première insertion de cette valeur dans la banque. Pour ce faire, je dois le laisser avec ID=1, CONTENT=first et PARENT=null car, après tout, il n'y a pas d'enregistrement parent comme celui-là (c'est le premier, après tout).
Ce qui serait fait naturellement?:
try (final var pstmt = conn.prepareStatement( """ INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?) """)) { pstmt.setInt(1, 1); pstmt.setString(2, "first"); pstmt.setNull(3, Types.INTGEGER); // java.sql.Types pstmt.executeUpdate(); // de fato altere o valor }
Je veux continuer à l'utiliser de cette fa?on, après tout, c'est la manière idiomatique de l'utiliser. Et selon CUPID, le I vient de ? idiomatique ?. L'idée d'avoir un code idiomatique est justement de "réduire la charge mentale inutile".
Pour résoudre ce problème, mon choix était : laisser préparerStatement jusqu'au dernier moment avant d'exécuterexecuteUpdate. Je stocke donc toutes les valeurs nulles à appliquer et, quand je réalise que j'ai réellement besoin d'une valeur nulle, j'exécute une substitution de cha?ne et génère une nouvelle requête, et cette nouvelle requête sera effectivement exécutée.
Dans ce cas, je commence par?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?)
Donc, je dois saisir ces valeurs?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?) -- 1, 'first', NULL
Mais je ne peux pas réellement utiliser le nul, alors je crée une clé pour identifier que la troisième place est un nul?:
-- (value, value, NULL) INSERT INTO some_table (id, content, parent) VALUES (?, ?, NULL) -- 1, 'first'
Et dans ce cas je prépare cette nouvelle cha?ne et place les arguments selon ce qui a été demandé.
D'accord, cela dit, comment pourrais-je indiquer à mon application que je devais utiliser mon pilote JDBC?? Comment je me suis inscrit ?
Le projet en question est Pstmt Null Safe. Fondamentalement, il existe une magie dans le chargeur de classe Java qui, lors du chargement d'un fichier jar, recherche un dossier de métadonnées appelé META-INF. Et dans le cas du pilote JDBC, META-INF/services/java.sql.Driver, et je l'ai noté avec la classe qui implémente java.sql.Driver?: br.com.softsite.pstmtnullsafe.jdbc.PstmtNullSafeDriver.
Selon la documentation java.sql.Driver, chaque pilote doit créer une instance de lui-même et s'enregistrer auprès de DriverManager. Je l'ai implémenté comme ceci?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?)
Le bloc statique se charge tout seul. Et comment savoir quelle connexion doit être gérée par mon chauffeur ? L'appel est effectué via DriverManager#getConnection(String url). Nous avons l'URL pour demander au chauffeur s'il accepte la connexion. La convention (là encore, la manière idiomatique de l'utiliser) est de le préfixer au schéma d'URL. Comme je veux que mon chauffeur se connecte au-dessus d'un autre chauffeur, je l'ai fait en utilisant ce schéma?:
try (final var pstmt = conn.prepareStatement( """ INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?) """)) { pstmt.setInt(1, 1); pstmt.setString(2, "first"); pstmt.setNull(3, Types.INTGEGER); // java.sql.Types pstmt.executeUpdate(); // de fato altere o valor }
Donc, pour effectuer les tests, je me suis connecté à SQLite, et j'ai utilisé l'indicateur Xerial pour demander une connexion en mémoire via l'URI de connexion?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?)
Pour "envelopper" la connexion, ma convention indique que je ne répète pas le jdbc:, donc :
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?) -- 1, 'first', NULL
Disséquer l'URI ci-dessus?:
-- (value, value, NULL) INSERT INTO some_table (id, content, parent) VALUES (?, ?, NULL) -- 1, 'first'
D'accord, et comment indiquez-vous cela ? Le Driver#acceptsURL doit renvoyer true si je peux ouvrir la connexion. Je pourrais juste faire ?a?:
public static final PstmtNullSafeDriver instance; static { instance = new PstmtNullSafeDriver(); try { DriverManager.registerDriver(instance); } catch (SQLException e) { e.printStackTrace(); } }
Mais qu'est-ce que cela indiquerait si j'essayais de charger un pilote inexistant?? Rien, cela poserait un problème à un autre moment. Et ce n'est pas bien, l'idéal serait de planter dès le début. Donc pour ?a, je vais essayer de charger le pilote par le bas, et si je n'y arrive pas, je renvoie false :
jdbc:pstmt-nullsafe:<url de conex?o sem jdbc:> \__/ \____________/ | | | Nome do meu driver Padr?o para indicar JDBC
Le code du pilote actuel contient d'autres points qui ne sont pas pertinents pour la discussion ici sur HikariCP, ni sur DataSource, ni sur JDBC ou sur les sujets abordés dans cet article.
Ainsi, lorsque vous demandez une connexion "null safe" à DriverManager, il trouve d'abord mon pilote et mon pilote essaie de manière récursive de vérifier s'il y a la possibilité d'une connexion sous le capot. Confirmé qu'il existe un chauffeur capable de gérer cela, je dis oui, c'est possible.
Le modèle d'utilisation des connexions JDBC en Java
L'interface de connexion implémente l'interface AutoCloseable. Cela signifie que vous prenez la connexion, l'utilisez comme vous le souhaitez, puis vous fermez la connexion. Il est tout à fait standard que vous utilisiez une certaine indirection avec ceci ou, si vous utilisez la connexion directement, utilisez-la dans un bloc try-with-resources:
jdbc:sqlite::memory:
Maintenant, le processus de création de connexions est un processus co?teux. Et de plus, le processus de découverte de services n'est pas vraiment gratuit. L'idéal serait donc de sauvegarder le driver pour ensuite générer les connexions. Développons cela petit à petit.
Tout d'abord, nous aurons besoin d'un objet que nous pouvons lancer avec le pilote. Il peut facilement s'agir d'un objet global, d'un composant Spring injecté ou quelque chose comme ?a. Appelons-le JdbcConnector?:
jdbc:pstmt-nullsafe:sqlite::memory:
Une implémentation possible pour getJdbcConnection() consiste à s'appuyer sur un état englobé par cette fonction?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?)
Tout va bien jusqu’à présent. Mais... vous vous souvenez de l'exemple initial où le paysan demande une houe dans la piscine à outils?? Alors... Devons-nous en tenir compte ? Au lieu de fermer réellement la connexion, nous pouvons rétablir la connexion au pool. Par souci d'exactitude, je me protégerai contre plusieurs accès simultanés, mais je ne me soucierai pas ici de l'efficacité.
Supposons ici que j'ai une classe appelée ConnectionDelegator. Il implémente toutes les méthodes Connection, mais il ne fait rien par lui-même, il délègue uniquement à une connexion qui lui est transmise en tant que constructeur. Par exemple, pour la méthode isClosed():
try (final var pstmt = conn.prepareStatement( """ INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?) """)) { pstmt.setInt(1, 1); pstmt.setString(2, "first"); pstmt.setNull(3, Types.INTGEGER); // java.sql.Types pstmt.executeUpdate(); // de fato altere o valor }
Et ainsi de suite pour les autres méthodes. C'est abstrait du simple fait que j'ai envie de me forcer à faire autre chose qu'une simple délégation lorsque je l'utilise.
Eh bien, allons-y. L'idée est qu'une connexion sera demandée, qui peut exister ou non. S'il existe, je l'enveloppe dans cette nouvelle classe pour pouvoir ensuite le renvoyer au pool lorsque je ferme la connexion. Hmmm, donc je vais faire quelque chose dans la méthode close()... Ok, finissons-en d'abord. Laissons getConnection() comme synchronisé pour éviter les problèmes de concurrence?:
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?)
Ok, si j'ai des éléments dans le pool de connexions je les utilise jusqu'à ce qu'il soit vide. Mais il n'est jamais rempli ! Alors allons-nous résoudre ce problème ? A la fermeture, nous pourrons le remettre à la piscine !
INSERT INTO some_table (id, content, parent) VALUES (?, ?, ?) -- 1, 'first', NULL
Ok, maintenant, lorsque vous avez fini d'utiliser la connexion, elle est renvoyée à
la piscine. Cela ne satisfait pas à la documentation de la méthode Connection#close(), car dans la documentation, il est mentionné qu'elle libère toutes les ressources JDBC liées à cette connexion. Cela signifie que je devrais conserver une trace de toutes les instructions, ResultSets, PreparedStatements, etc. Nous pouvons gérer cela en créant une méthode protégée sur ConnectionDelegator appelée closeAllInnerResources(). Et appelez-le close()?:
-- (value, value, NULL) INSERT INTO some_table (id, content, parent) VALUES (?, ?, NULL) -- 1, 'first'
Et avec ?a nous avons quelque chose qui me renvoie des connexions à la demande et qui a la capacité de former un pool de ressources.
Savez-vous quel nom Java donne à un objet qui fournit des connexions?? Source de données. Et savez-vous ce que Java a à dire d'autre sur les DataSources?? Qu'il existe certains types, conceptuellement parlant. Et parmi ces types, les 2 plus pertinents sont?:
- de base?: il ne fait pas de pooling, il a demandé une connexion, il la crée et la renvoie simplement
- pooled : dans lequel il existe une mutualisation des connexions à la banque
Et ici nous passons par le processus de toujours créer des connexions (type de base) ainsi que d'évoluer vers une DataSource
mutué.
Qu’est-ce qu’HikariCP??
HikariCP est une source de données. Plus précisément, une DataSource regroupée. Mais il a une particularité : il est le plus rapide de tous. Pour garantir cette rapidité, dans son pool de connexions à utiliser pendant le cycle de vie de l'application, HikariCP fait un secret : il crée déjà toutes les connexions disponibles. Ainsi, lorsqu'un getConnection arrive, HikariCP n'aura qu'à vérifier le pool de connexions.
Si vous souhaitez approfondir le sujet, vous pouvez consulter cet article sur Baeldung sur le sujet, et également consulter le référentiel sur github.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1
éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

La différence entre le hashmap et le hashtable se reflète principalement dans la sécurité des threads, la prise en charge de la valeur nul et les performances. 1. En termes de sécurité des threads, le hashtable est en filetage et ses méthodes sont principalement des méthodes synchrones, tandis que HashMAP n'effectue pas de traitement de synchronisation, qui n'est pas un filetage; 2. En termes de support de valeur nulle, HashMap permet une clé nul et plusieurs valeurs nulles, tandis que le hashtable ne permet pas les clés ou les valeurs nulles, sinon une nulpointerexception sera lancée; 3. En termes de performances, le hashmap est plus efficace car il n'y a pas de mécanisme de synchronisation et le hashtable a une faible performance de verrouillage pour chaque opération. Il est recommandé d'utiliser à la place ConcurrentHashMap.

Java utilise des classes de wrapper car les types de données de base ne peuvent pas participer directement aux opérations orientées objet, et les formulaires d'objets sont souvent nécessaires dans les besoins réels; 1. Les classes de collecte ne peuvent stocker que des objets, tels que les listes, l'utilisation de la boxe automatique pour stocker des valeurs numériques; 2. Les génériques ne prennent pas en charge les types de base et les classes d'emballage doivent être utilisées comme paramètres de type; 3. Les classes d'emballage peuvent représenter les valeurs nulles pour distinguer les données non définies ou manquantes; 4. Les cours d'emballage fournissent des méthodes pratiques telles que la conversion de cha?nes pour faciliter l'analyse et le traitement des données, donc dans les scénarios où ces caractéristiques sont nécessaires, les classes de packaging sont indispensables.

Le compilateur JIT optimise le code à travers quatre méthodes: méthode en ligne, détection et compilation de points chauds, spéculation et dévigtualisation de type et élimination redondante. 1. La méthode en ligne réduit les frais généraux d'appel et inserte fréquemment appelées petites méthodes directement dans l'appel; 2. Détection de points chauds et exécution de code haute fréquence et optimiser de manière centralisée pour économiser des ressources; 3. Type Speculations collecte les informations de type d'exécution pour réaliser des appels de déviptualisation, améliorant l'efficacité; 4. Les opérations redondantes éliminent les calculs et les inspections inutiles en fonction de la suppression des données opérationnelles, améliorant les performances.

StaticMethodsinInterfaceswereintrocedInjava8TollowutilityfonctionwithIntheInterface self.beforejava8, telfunctionsrequuresepatehelperclasses, leadstodisorganizedCode.now, staticmethodsprovidethrekeyefits: 1) ils sont en train

Les blocs d'initialisation d'instance sont utilisés dans Java pour exécuter la logique d'initialisation lors de la création d'objets, qui sont exécutés avant le constructeur. Il convient aux scénarios où plusieurs constructeurs partagent le code d'initialisation, l'initialisation du champ complexe ou les scénarios d'initialisation de classe anonyme. Contrairement aux blocs d'initialisation statiques, il est exécuté à chaque fois qu'il est instancié, tandis que les blocs d'initialisation statiques ne s'exécutent qu'une seule fois lorsque la classe est chargée.

Injava, thefinalkeywordpreventsavariable'svaluefrombeingchangedafterAsssignment, mais cetsbehaviDiffersFortimitives et objectreferences.forprimitivevariables, finalMakeShevalueConstant, AsinfininTMax_peed = 100; whitereSsignmentCausAnesanerror.ForobjectRe

Le mode d'usine est utilisé pour encapsuler la logique de création d'objets, ce qui rend le code plus flexible, facile à entretenir et à couplé de manière lache. La réponse principale est: en gérant de manière centralisée la logique de création d'objets, en cachant les détails de l'implémentation et en soutenant la création de plusieurs objets liés. La description spécifique est la suivante: Le mode d'usine remet la création d'objets à une classe ou une méthode d'usine spéciale pour le traitement, en évitant directement l'utilisation de newClass (); Il convient aux scénarios où plusieurs types d'objets connexes sont créés, la logique de création peut changer et les détails d'implémentation doivent être cachés; Par exemple, dans le processeur de paiement, Stripe, PayPal et d'autres instances sont créés par le biais d'usines; Son implémentation comprend l'objet renvoyé par la classe d'usine en fonction des paramètres d'entrée, et tous les objets réalisent une interface commune; Les variantes communes incluent des usines simples, des méthodes d'usine et des usines abstraites, qui conviennent à différentes complexités.

Il existe deux types de conversion: implicite et explicite. 1. La conversion implicite se produit automatiquement, comme la conversion INT en double; 2. La conversion explicite nécessite un fonctionnement manuel, comme l'utilisation de (int) MyDouble. Un cas où la conversion de type est requise comprend le traitement de l'entrée des utilisateurs, les opérations mathématiques ou le passage de différents types de valeurs entre les fonctions. Les problèmes qui doivent être notés sont les suivants: transformer les nombres à virgule flottante en entiers tronqueront la partie fractionnaire, transformer les grands types en petits types peut entra?ner une perte de données, et certaines langues ne permettent pas la conversion directe de types spécifiques. Une bonne compréhension des règles de conversion du langage permet d'éviter les erreurs.
