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

JPA Java Discussion :

Pas d'update après un flush


Sujet :

JPA Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut Pas d'update après un flush
    Bonjour,

    Dans une application utilisant JPA (hibernate) pour persister nos données, nous avons mis en place un DAO générique avec, entre autre, une méthode "save" dont le but est de sauver un objet, qu'il soit managé ou non par hibernate.

    L'implémentation est la suivante :
    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
     
    public class AbstractGenericDao<T extends Identifiable> {
        ...
        @PersistenceContext(unitName="AppPeristanceUnit")
        protected EntityManager em = null;
        ...
        @Transactional(readOnly = false)
        public T save(T entity) {
      	if (entity.getId() == null) {
    		em.persist(entity);
    		em.flush();
    		return entity;
    	} else {
    		T newEntity = em.merge(entity);
    		em.flush();
    		return newEntity;
    	}
    }
    Jusqu'à présent il a toujours bien fonctionné.
    Mais récemment, dans une application qui importe des données j'ai eu des problèmes de modification non sauvées, et ce malgré le flush.
    La table source de l'import comprend un champ qu'on flag pour savoir si l'enregistrement a été importé.
    Les enregistrements étaient importés par paquet de 50 et en changeant ce nombre à 1, j'ai constaté qu'après un certain temps, l'importer se mettait à importer en boucle le même enregistrement car son flag n'était pas sauvé.
    Dans le log de l'application je ne vois plus la requête d'update (qui était présente avant qu'il se mette à boucler), j'en conclus donc que ma méthode save n'a pas bien fait son boulot ...
    Mais pourquoi ... ?

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut
    Il semblerait que mon problème est dû à des accès concurrent.

    Dans mon environnement de test, si je lance l'importation seule, aucun problème.
    Mais si je lance l'importation et que pendant qu'elle tourne je modifie les données en cours d'import, l'importation se bloque sur l'instruction d'update et reprend dès que je commit les modification dans Oracle SQL developper :

    - update 86 records dans Oracle SQL developper
    - commit
    - démarrage de l'importer
    - update des même 86 records
    - importer bloqué sur l'instruction d'update (la requete SQL est loggué dans la console)
    - commit
    - reprise de l'import mais en boucle sur un record.

    Je n'ai pas la moindre idée du comment régler ça

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut
    J'ai trouvé un dépannage :

    c'est pas optimale mais pour le moment ça à l'air de tenir :

    juste avant de valoriser le flag et de sauver le record, je le refresh (entityManager.refresh).

    Le bémol, c'est que cette façon de géré ne tient pas compte des éventuelles modifications qui auraient pu être faites. (le record ne sera pas ré-importé avec les nouvelles modifications.)

  4. #4
    Membre éclairé Avatar de Jacobian
    Inscrit en
    Février 2008
    Messages
    425
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 425
    Par défaut
    je comprend pas trop ton souci du fait que c'est toi qui bloc le programme en vérrouillon la table par un update dans plsqldevelopper ??

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut
    En environnement réel, la table des données à importé est modifiée par une programme tiers.
    Mon programme d'import est planifié pour tourner toutes les 2 minutes.

    Pour reproduire le problème en environnement de test, je met à jour cette table en exécutant manuellement une requête d'update dans SQL Developper pendant que mon import tourne.

    Au moment ou j'exécute ce query, mon importer va se bloquer sur la requête d'update de la même table (probablement un système de verrou sur les accès concurrent)

    Et c'est seulement lorsque je vais commit dans SQL developper que l'importer rependre son cours (mais en bouclant sur le même record)

    Le problème n'est pas le bloquage, car en stuation réelle, les commits sont fait immédiatement. Le problème c'est qu'après ce commit, mon importer s'embrouille et boucle sur le même record.

    Je ne sais pas si c'est plus clair

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Comment gères tu tes transactions ?
    Il y a des chances que le problème vienne de là.

    Déjà, poser un attribut transactionnel sur ta méthode save, je ne vois pas trop l'intérêt.

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut
    Alors,
    d'abord je charge le record à importer en DB (pas de transaction)
    Ensuite une transaction (non read-only) est ouverte pour chaque record à importer.
    Si l'import réussi, je sauve le statut du record ("done") dans la transaction.
    Si l'import échoue, je roll-back et sauve le status de l'import ("error") en dehors de cette transaction.

    L'attribut transactionnel sur la méthode save à pour but de permettre l'écriture. Si je ne le mets pas, il n'y aura jamais de persistance, par défaut les transactions sont ouverte en "readOnly=true"

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

Discussions similaires

  1. pourquoi update apres insertInto ?
    Par Shivan dans le forum Hibernate
    Réponses: 2
    Dernier message: 21/02/2007, 18h07
  2. [CKEditor] browser server files => ne se met pas a jour apres un CreateFolder
    Par otb82 dans le forum Bibliothèques & Frameworks
    Réponses: 1
    Dernier message: 20/02/2007, 11h52
  3. Réponses: 2
    Dernier message: 12/01/2007, 01h27
  4. Réponses: 4
    Dernier message: 17/10/2006, 15h11
  5. Réponses: 13
    Dernier message: 20/03/2006, 16h26

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