Question

J'utilise hibernate 3 avec c3p0 pour un programme qui extrait en permanence des données d'une source et les écrit dans une base de données. Le problème, c’est que la base de données risque de ne plus être disponible pour certaines raisons (dans le cas le plus simple: je la ferme tout simplement).

Si quelque chose est sur le point d'être écrit dans la base de données, il ne devrait y avoir aucune exception. La requête doit attendre toute la durée de l'éternité jusqu'à ce que la base de données redevienne disponible. Si je ne me trompe pas, c'est l'une des choses que le pool de connexion pourrait faire pour moi: s'il y a un problème avec la base de données, essayez simplement de vous connecter - dans le pire des cas pour l'infini.

Mais au lieu de cela, j'ai une exception de canal cassé, parfois suivie d'une connexion refusée, puis cette exception est transmise à mon propre code, ce qui ne devrait pas se produire.

Même si j'attrape l'exception, comment pourrais-je réinitialiser hibernation proprement? (Jusqu'à présent, sans c3p0, j'ai simplement construit à nouveau la fabrique de sessions, mais je ne serais pas surpris que cela puisse provoquer des fuites dans les connexions (ou est-ce que cela est acceptable?)).

La base de données est une édition open source Virtuoso.

Mon hibernate.xml.cfg c3p0 config:

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
<property name="hibernate.c3p0.breakAfterAcquireFailure">false</property>
<property name="hibernate.c3p0.acquireRetryAttempts">-1</property>
<property name="hibernate.c3p0.acquireRetryDelay">30000</property>
<property name="hibernate.c3p0.automaticTestTable">my_test_table</property>

<property name="hibernate.c3p0.initialPoolSize">3</property>
<property name="hibernate.c3p0.minPoolSize">3</property>
<property name="hibernate.c3p0.maxPoolSize">10</property>

btw: La table de test est créée et j'obtiens des tonnes de sorties de débogage. Il semble donc qu'il lit réellement la configuration.

Était-ce utile?

La solution

Eh bien, il semble que BoneCP l’ait réellement mis en œuvre. Il peut être configuré pour enregistrer la transaction et la rejouer en cas de défaillance du réseau ou de la base de données:

http: // jolbox.com/bonecp/downloads/site/apidocs/com/jolbox/bonecp/BoneCPConfig.html#setTransactionRecoveryEnabled(boolean)

Autres conseils

  

Si je ne me trompe pas, c'est l'une des choses que le pool de connexion pourrait faire pour moi: s'il y a un problème avec la base de données, essayez simplement de vous connecter - dans le pire des cas pour l'infini.

Vous vous trompez. Un pool de connexions est simplement ... un pool de connexions, il contient des connexions physiques déjà établies à la base de données et permet d'éviter la surcharge liée à la création de ces connexions lorsque vous en avez besoin.

Cela dit, ces connexions peuvent devenir obsolètes (par exemple, si vous redémarrez la base de données). Heureusement, la plupart des pools de connexions peuvent être configurés pour vérifier si une connexion est toujours valide et les renouveler avant de les distribuer. c3p0 prend en charge cette fonctionnalité, comme indiqué dans la Configuration du test de connexion . utilise déjà l'une des différentes options. Vos connexions doivent donc être renouvelées lorsque la base de données sera rétablie.

Mais ne vous attendez pas à ce que votre application soit suspendue comme par magie lorsque la base de données tombe en panne, un pool ne le fera pas.

Merci pour la réponse. Il semble que je n'ai pas vraiment compris le dernier paragraphe de la section http://www.mchange.com/projects/c3p0/index.html# configuration_recuperation

Parce qu’au premier abord il semble que c3p0 puisse le faire (détecter les connexions obsolètes et réessayer d’acquérir des connexions pour toute l’éternité sans jamais lever une exception au code de l’application (à moins bien sûr que ce soit une erreur liée à l’instruction SQL et non au connexion), mais dans le dernier paragraphe - qui est écrit de manière assez confuse - il semble que c3p0 ne puisse pas garantir cela à 100%.

Donc, ma solution a été de créer un petit wrapper pour les méthodes dont j'avais besoin à partir de l'interface de connexion jdbc, qui tente de se reconnecter si une requête échoue à cause d'une erreur de connexion. Bien sûr, c'est un peu compliqué, parce que je préférerais que mes composants utilisent l'interface standard de Connection au lieu de ma propre interface, mais au moins, ils fonctionnent correctement maintenant.

Vous oubliez:

  • Qu'en est-il des transactions que vous avez commencées?
  • Qu'en est-il des déclarations préparées qui ont déjà été envoyées à la base de données?
  • etc

Votre application devra donc redémarrer la transaction. La seule façon dont je puisse penser est que le pool de connexions garde la trace de tous les appels du descripteur de connexion et les rejoue en cas d'erreur, mais cela ralentirait considérablement le pool de connexions.

Dans le cas de BoneCP ( http://jolbox.com ), le pool détecte qu'un échec est survenu par attrapez d'abord l'exception lancée par le pilote JDBC et gérez-la en signalant cette connexion comme défectueuse ou en recréant l'intégralité du pool de connexions.

Éditer: c'est en cours de traitement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top