IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Hibernate Java Discussion :

[MultiThreading - Hibernate] : problème de création de socket au bout d'un certain temps


Sujet :

Hibernate Java

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2014
    Messages : 11
    Points : 6
    Points
    6
    Par défaut [MultiThreading - Hibernate] : problème de création de socket au bout d'un certain temps
    Bonjour à tous
    J'ai à alimenter une base de données via un programme Java.
    Pour ce programme, j'ai utilisé Spring et Hibernate, et j'ai dû m'essayer à faire des Thread (1ère fois que j'en fais).
    J'ai utilisé Executor (du package java.util.concurrent) car on me demande de faire un programme optimisé et rapide.
    J'utilise un pool de thread.
    Le programme fonctionne bien, pendant environ 45 secondes et après, j'obtiens cette erreur répétée plusieurs fois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Exception in thread "pool-1-thread-593" org.hibernate.exception.JDBCConnectionException: Cannot open connection
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:99)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
    at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
    at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
    at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
    at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1463)
    at fr.msa.agora.bp0gos.qualification.structure.InjecteurFluxStructureRFOSImpl$UnitOfWork.run(InjecteurFluxStructureRFOSImpl.java:107)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
    Caused by: java.sql.SQLException: socket creation error
    at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
    at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
    at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
    at org.hsqldb.jdbcDriver.connect(Unknown Source)
    at org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
    at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:294)
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:840)
    at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:96)
    at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
    at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)

    Voici une partie de mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
     
    @Service("InjecteurStructure")
    public class InjecteurFluxStructureRFOSImpl extends AbstractInjecteurFluxRFOS implements InjecteurFluxRFOS {
     
    private final StructureRFOS2StructureGOSMapperImpl mapper;
     
    @Autowired
    public InjecteurFluxStructureRFOSImpl(final StructureRFOS2StructureGOSMapperImpl pMapper,
    final SessionFactory pSession, final Executor pPoolDeThread, final GestionRepertoire pGestionRepertoire) {
    super(pSession, pPoolDeThread, pGestionRepertoire);
    mapper = pMapper;
    }
     
    @Override
    public void mapUnFichier(final File pFichier) {
    final RFOSStructure structureFichier = JAXB.unmarshal(pFichier, RFOSStructure.class);
    persisterTable(structureFichier.getSTS());
    }
     
    private void persisterTable(final STS pStructureSTS) {
    final UnitOfWork unit = new UnitOfWork(mapper, sessionFactory, pStructureSTS);
    poolDeThread.execute(unit);
    }
     
    private static class UnitOfWork implements Runnable {
     
    private final StructureRFOS2StructureGOSMapperImpl mapper;
     
    private final SessionFactory sessionFactory;
     
    private final STS structureSTS;
     
    public UnitOfWork(final StructureRFOS2StructureGOSMapperImpl pMapper, final SessionFactory pSession,
    final STS pStructureSTS) {
    mapper = pMapper;
    sessionFactory = pSession;
    structureSTS = pStructureSTS;
    }
     
    /*
    * (non-Javadoc)
    * 
    * @see java.lang.Runnable#run()
    */
    @Override
    public void run() {
    final Session session = sessionFactory.openSession();
    try {
     
    final fr.msa.agora.bp0gos.metier.sts.domaine.STS structureGOS = mapper.map(structureSTS);
     
    final Transaction transaction = session.beginTransaction();
    try {
    session.save(structureGOS);
    session.flush();
    transaction.commit();
     
    } catch (final RuntimeException r) {
    transaction.rollback();
    throw r;
    } catch (final Error error) {
    transaction.rollback();
    throw error;
    }
    } finally {
    session.close();
    }
    }
    }
     
    }
    Merci d'avance à vous tous,
    Thomas

    PS: La volumétrie est d'environ 90000 fichiers à parser, afin d'alimenter la base de données.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Combien tu as de Threads dans ton ThreadPool? Ce message indique qu'il n'y a plus de place pour de nouvelles connections à la base de données. Il peux y avoir 2 raisons:

    1) tu ne ferme pas les connection => il y a un session.close dans une finally à la fin de ton run, donc je n'y crois pas trop
    2) tu a mis tellement de threads en parallèle que la base de données est saturées => ton executor doit être limité en taille sinon tout ce que tu parviendra à faire c'est à mettre ton programme à genoux.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2014
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Combien tu as de Threads dans ton ThreadPool? Ce message indique qu'il n'y a plus de place pour de nouvelles connections à la base de données. Il peux y avoir 2 raisons:

    1) tu ne ferme pas les connection => il y a un session.close dans une finally à la fin de ton run, donc je n'y crois pas trop
    2) tu a mis tellement de threads en parallèle que la base de données est saturées => ton executor doit être limité en taille sinon tout ce que tu parviendra à faire c'est à mettre ton programme à genoux.
    Tchize, je te remercie pour ta réponse.

    Ton Hypothèse n° 1 : Comme tu dis, je ferme bien les connexions.

    Ton Hypothèse n° 2 : Je débute en Thread, je n'en ai jamais utilisé, j'ai juste là essayé de m'inspirer de ce que j'avais pu voir.
    Comment limiter le nombre de Thread ? C'est dans le code je suppose ?
    Car, dans mon programme, j'ai 97331 fichiers XML à parser, aussi la méthode mapUnFichier est appelée 97331 fois, et finalement la méthode persisterTable est appelée 97331 fois. Donc je crée 97331 UnitOfWork.
    Cela peut-il poser problème ?
    Dans ce cas, je dois toucher au code ?

    Encore Merci tchize, et bonne fin de journée,
    Thomas

    PS : Dans mon fichier de configurration Hibernate, j'ai touché aux paramètres, mais cela n'a aucun effet.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bdd.pool.maxActive=300
    bdd.pool.maxWait=-1
    bdd.pool.maxIdle=100
    hibernate.c3p0.min_size=5
    hibernate.c3p0.max_size=100
    hibernate.c3p0.timeout=2800
    hibernate.c3p0.max_statements=350

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par thomasToulouse Voir le message
    Comment limiter le nombre de Thread ? C'est dans le code je suppose ?
    Donc je crée 97331 UnitOfWork.
    Cela peut-il poser problème ?
    Uniquement si tout tourne en même temps. Mais de toutes façons, à 2000 unités en parallèle, c'est l'OS qui commencera à t'envoyer péter

    Pour limiter, tout se trouve dans la manière dont tu instancie ton Executor. Tu peux nous montrer ce code là?

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2014
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Uniquement si tout tourne en même temps. Mais de toutes façons, à 2000 unités en parallèle, c'est l'OS qui commencera à t'envoyer péter

    Pour limiter, tout se trouve dans la manière dont tu instancie ton Executor. Tu peux nous montrer ce code là?
    Bonjour tchize.
    Je te remercie beaucoup de te pencher sur mon problème.
    En fait, je l'instanciais via Spring mais maintenant j'utilise l'instruction suivante : Executors.newFixedThreadPool(5)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    package fr.msa.agora.bp0gos.qualification.commun;
    import java.io.File;
    import java.util.concurrent.Executor;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    /**
     * Classe abstraite regroupant le traitement générique à tous les types d'injection.
     * 
     * 
     */
    @Service
    public abstract class AbstractInjecteurFluxRFOS implements InjecteurFluxRFOS {
        /**
         * Fabrique de sessions Hibernate.
         */
        protected final SessionFactory sessionFactory;
        /**
         * Pool de Threads.
         */
        protected final ExecutorService poolDeThread;
        /**
         * Service des opérations pouvant être effectuées sur un répertoire.
         */
        protected final GestionRepertoire gestionRepertoire;
        /**
         * Constructeur injectant les services.
         * 
         * @param pSessionFactory factory de session Hibernate.
         * @param pPoolDeThread pool de Threads.
         * @param pGestionRepertoire service de lecture des fichiers d'un répertoire.
         */
        @Autowired
        public AbstractInjecteurFluxRFOS(final SessionFactory pSessionFactory, final Executor pPoolDeThread,
                final GestionRepertoire pGestionRepertoire) {
            sessionFactory = pSessionFactory;
            //        poolDeThread = pPoolDeThread;
            poolDeThread = Executors.newFixedThreadPool(5);
            gestionRepertoire = pGestionRepertoire;
        }
        /**
         * Alimente la base de données à partir des flux XML se trouvant dans le répertoire dont le nom est passé en
         * paramètre.
         * 
         * @param pDossierFlux nom du répertoire où se trouvent nos fichiers XML.
         */
        public void alimenteBDDGos(final String pDossierFlux) {
            // Itération sur les fichiers
            final File[] listeFichiers = iterationFichier(pDossierFlux);
            final int i = listeFichiers.length;
            System.out.println("///////////////// i = " + i);
            final ExecutorCompletionService ecs = new ExecutorCompletionService(poolDeThread);
            final int j = 0;
            // Traitement des fichiers
            for (final File fichierAMapper : listeFichiers) {
                //            // extrait du fichier les données et les sauvegarde dans la BDD au bon format
                mapUnFichier(fichierAMapper);
            }
        }
        /**
         * Lit séquentiellement les fichiers XML présents dans le répertoire passé en paramètre.
         * 
         * @param répertoire où doivent être lus les fichiers de type XML.
         * @return la liste des fichiers XML présents dans ce fichier, vide sinon.
         */
        private File[] iterationFichier(final String pRepertoireFlux) {
            return gestionRepertoire.lectureFiltree(pRepertoireFlux, "xml");
        }
        /**
         * Méthode d'alimentation de la base de données à partir d'un flux XML : doit être défini pour chaque type
         * d'injection.
         * 
         * @param pFichier fichier servant à l'alimentation de la base de données.
         */
        public abstract void mapUnFichier(final File pFichier);
    }
    Encore Merci.
    Je vais relancer mon Eclipse (qui a quelque souci) et je te tiens au courant.
    Bonne journée tchize.
    Thomas

    PS: En fait, j'ai différents injecteurs, en fonction du type d'injection à réaliser : pour l'entité nommée "Structure", c'est la classe que j'ai montrée dans mon 1er message chargée d'alimenter la base avec des structures issues de fichiers XML, pour un autre type d'entité, c'est un autre type d'injecteur, etc....
    Tous ces injecteurs héritent d'une classe mère (celle que je montre dans ce message) où j'ai factorisé tout le code commun aux différents "injecteurs".

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2014
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Tchize, tu es un champion.
    Je n'ai plus ce problème.
    J'ai un autre problème qui fera l'objet d'un autre post.
    Mais je n'ai plus le problème de connexion empêchée au bout d'un certain temps.
    Encore Merci chef.
    Comme tu le préconisais, la solution consistait à limiter le nombre de Thread de cette manière : Executors.newFixedThreadPool(5)
    Thomas

    PS/ Est-ce que tu connaîtrais un livre ou un tutorial du style "Executor pour les nuls", où on explique dans le détail ce qui se passe :
    - dans quoi sont stockées les tâches ?
    - comment se passe l'activité des Threads ?
    Un livre ou un tuto (même en anglais) très très détaillé ?

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par thomasToulouse Voir le message
    - dans quoi sont stockées les tâches ?
    Ce n'est pas précisé dans la doc, ça dépend de l'Executor
    Citation Envoyé par thomasToulouse Voir le message
    - comment se passe l'activité des Threads ?
    Ca dépend aussi de l'executor, cf la javadoc où chaque comportement est expliqué

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2014
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Encore Merci tchize.
    Je vais essayer d'approfondir le sujet.
    Si j'en ai le temps et l'énergie.
    Mais c'est vrai que j'aimerais bien.
    Je te remercie encore beaucoup tchize.
    Thomas

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. problème pour la création de socket en suivant le tuto
    Par Steph1904 dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 09/10/2010, 17h07
  2. Problème de création de socket
    Par Kaneda Shotaro dans le forum C#
    Réponses: 13
    Dernier message: 27/11/2009, 10h12
  3. Réponses: 0
    Dernier message: 07/09/2008, 13h42
  4. Problème de création de fenêtre
    Par tomateauketchup dans le forum DirectX
    Réponses: 1
    Dernier message: 08/06/2003, 19h42
  5. [Rave Report] problème de création dynamique
    Par Nivux dans le forum Rave
    Réponses: 2
    Dernier message: 24/05/2003, 00h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo