m'aider à éviter d'attente de la connexion avec JPA, Hibernate & MySQL
Je suis en utilisant JPA (Hibernate en tant que fournisseur), Glassfish et MySQL. Tout fonctionne très bien en développement, mais quand j'ai déployer l'application sur un serveur de test et de le laisser fonctionner (en grande partie en veille) pour la nuit, je suis généralement accueillis avec cela le matin:
[#|2011-03-09T15:06:00.229+0000|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=23;_ThreadName=Thread-1;|ERROR [htt\
p-thread-pool-8080-(1)] (JDBCTransaction.java:91) - JDBC begin failed
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 41,936,868 milliseconds ago. The last packet \
sent successfully to the server was 41,936,868 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expirin\
g and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connec\
tion property 'autoReconnect=true' to avoid this problem.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1118)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3321)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1940)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2562)
at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4956)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:87)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:60)
J'ai essayé à l'aide de la suite dans mon persistence.xml
, mais il n'a pas aidé:
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.idleTestPeriod" value="30"/>
<property name="hibernate.c3p0.timeout" value="0"/>
<property name="hibernate.c3p0.max_statements" value="0"/>
De sorte que la C3p0 de configuration; il est tout à fait possible que je me manque la partie réellement indique à hibernate "hé, utilisez c3p0".
Je suis sur le point d'essayer la suggestion qui est là, dans le message d'erreur: ajouter autoReconnect=true
à mon URL JDBC, mais c'est vraiment de commencer à se sentir comme cargo culte de développement à ce point. J'aimerais avoir quelques conseils sur la bonne façon de répondre à cette question. C'est difficile à déboguer, parce que le cycle de test est effectivement "fonctionne toute la nuit, de voir ce qui se passe dans la matinée".
Je devrais probablement mentionner à quel point je suis en fait en utilisant des connexions dans mon application. J'ai un custom Filtre De Servlet qui intercepte toutes les requêtes. Il crée un EntityManager, il les stocke dans un ThreadLocal, et est fermé par le filtre dans un catch/finally bloc. Toutes mes entités obtenir une référence à la EntityManager
de la ThreadLocal
.
Il est tout à fait possible que mon filtre est en faute, mais comme elle ne semble se produire après des périodes d'inactivité, je soupçonne autre chose est erroné. J'ai l'intention d'aller à la Couture/Soudure quand j'ai une chance de reprendre mon souffle, mais pour l'instant je suis plutôt sur ce filtre.
Edit: voici le TL;DR solution:
- utiliser votre conteneur du pool de connexion, si vous le pouvez (merci, @partenon)
- assurez-vous que votre pool de connexion utilise connexion de validation (merci, @matt b)
Dans mon cas, j'ai dû aller dans Glassfish console, à la rubrique Ressources/JDBC/Pools de Connexion, Onglet Avancé, puis activez la Connexion de Validation:
C'était vraiment une étape cruciale. Vous aussi vous voulez probablement pour définir Validate At Most Once
à quelque chose de raisonnable, de 100 secondes. Si vous êtes à l'aide de C3P0 ou similaire, assurez-vous de configurer idle_test_period
et preferredTestQuery
.
Tout ce que vous finissez par faire, il est important de tester vos modifications pour voir si ils ont l'effet désiré. Pour rendre le délai d'attente arriver plus vite dans MySQL, vous pouvez activer temporairement l' wait_timeout
à quelque chose de faible, comme 30 secondes par l'édition my.cnf
. Ce fut d'une grande aide au débogage de ce problème, car il m'a permis de tester en quelques secondes, plutôt qu'en heures.
OriginalL'auteur George Armhold | 2011-03-09
Vous devez vous connecter pour publier un commentaire.
Juste un coup de feu dans l'obscurité, mais avez-vous pris un coup d'oeil à la définition de la
autoReconnect=true
propriété dans votre pilote JDBC? Ou pensez à désactiver le paramètre côté serveur pour le client, les délais de connexion.Ne fonctionne pas - pas encore réussi à le même comportement en dépit de la autoReconnect param.
Revoir ce après une couple de mois. 'autoReconnect' n'a pas aider, mais votre suggestion de tester la connexion avant de l'utiliser était sur place.
OriginalL'auteur matt b
Je pense que la vraie question est: pourquoi êtes-vous à l'aide d'une connexion externe mécanisme de mise en commun au lieu d'utiliser Glassfish propre mise en commun? Votre serveur d'application est le mieux adapté pour fournir ce type de service pour votre application. "Externe" pooling de connexion mécanismes sont mieux adaptés pour des applications autonomes, pas dans le conteneur d'applications.
Votre demande ne sera pas compter sur une application particulière du serveur pour que. Dans la plupart des cas, vous utiliserez un "particulier" JNDI de la syntaxe. La seule chose que vous devez faire est de demander Hibernate pour obtenir la source de données à partir de JNDI.
Cette en effet résolu le problème pour moi, mais c'est à ce prix - je ne peux plus exécuter des tests unitaires ou de classes autonomes avec main() en dehors de l'application serveur, depuis le pool de connexions est évidemment pas disponible. Comme solution de contournement, je maintiens séparé persistence-unit qui a mes paramètres d'origine, et de les utiliser pour des tests en ligne de commande et des emplois. Merci!
OriginalL'auteur jpkrohling
Je pense que la propriété à définir la connexion de la période d'essai est de
idle_test_period
, pasidleTestPeriod
comme par C3P0 documentation ici. Donc, vous devriez être en utilisant:à la place.
OriginalL'auteur Binil Thomas
J'ai fait le même problème et il a fallu du temps pour trouver la solution.
J'utilise Hibernate 4.0.1 et mysql 5.1(pas de ressort), et un cadre, j'ai été confronté à la question. D'abord assurez-vous que vous avez configuré le c3p0 pots correctement, ce qui est essentiel.
J'ai utilisé ces propriétés dans hibernate.cfg.xml
Mais il ne sert à rien " cause C3p0 toujours les propriétés par défaut de ne pas les propriétés que j'ai mis dans hibernate.cfg.xml Vous pouvez le vérifier dans les journaux. Donc, j'ai cherché sur de nombreux sites web pour le droit de solution et finalement, je suis venu avec cette. supprimer la C3p0 propriétés dans cfg.xml et créer c3p0-config.xml dans le chemin de la racine(avec cfg.xml) et de définir les propriétés comme suit.
mais, si vous exécutez, ORM prend de la connexion jdbc, mais pas C3p0 pool de connexion " on doit ajouter ces propriétés dans hibernate.cfg.xml
maintenant tout fonctionne très bien(Au moins il a bien fonctionné pour moi) et le problème est résolu.
vérifiez les éléments suivants pour les références.
http://www.mchange.com/projects/c3p0/index.html#configuring_connection_testing
https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool
J'espère que cela résout votre problème.
OriginalL'auteur chaitanya89