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 :

StaleStateExecption (Batch update returned unexpected row) [Mapping]


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 34
    Par défaut StaleStateExecption (Batch update returned unexpected row)
    Bonjour à tous,

    je viens vers car je suis bloqué depuis plusieurs jours sur un soucis dont ne je comprend pas la cause et ce malgré énormément de recherche.

    Pour faire simple. J'ai deux objets A et B et indépendant l'un de l'autre qui update un même bag d'objet C.
    Le problème c'est qu'à partir du moment ou je place un cascade sur le bag ( de l'objet c) de l'objet B dès que j'update le bag (c) de l'objet A. J'ai l'erreur suivante.
    Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    Dans les logs on voit qu'hibernate, au moment du flush, veux update une row qui vient d'être supprimé.
    Infos: Hibernate: update t_cepp_ligne_de_compte set action_id=null where action_id=?
    Infos: Hibernate: delete from t_cepp_ligne_de_compte where ligne_de_compte_id=?
    Infos: Hibernate: delete from t_cepp_ligne_de_compte where ligne_de_compte_id=?
    Infos: Hibernate: delete from t_cepp_ligne_de_compte where ligne_de_compte_id=?
    Infos: Hibernate: delete from t_cepp_ligne_de_compte where ligne_de_compte_id=?

    update t_cepp_ligne_de_compte set utilisateur_id=?, campagne_id=?, type_operation_id=?, compte_cible_id=?, compte_source_id=?, action_id=?, valeur=?, actif=?, date_operation=?, date_modification=? where ligne_de_compte_id=?
    Infos: 11:49:52.429 ERROR f.g.a.o.p.h.HibernateTransaction - Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    Au début mon objet A avait plusieurs associations avec de nombreux autres objets qui pouvaient être lié à l'objet B. Ce qui entraînait une boucle et une exception que j'ai géré en supprimant ces associations. (en les remplaçant par un simple id dans les fichiers de mapping et les entity).
    Est-ce que laissé les FK dans la bdd pourrait jouer sur l'exception que throw hibernate ?

    Voici mon mapping.
    Objet A : t_cepp_action
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- Generated 25 sept. 2015 09:55:44 by Hibernate Tools 4.3.1 -->
    <hibernate-mapping>
      <class name="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppAction" optimistic-lock="version" schema="cepp_datas" table="t_cepp_action">
        <id name="actionId" type="integer" column="action_id"> 
            <generator class="sequence">
                <param name="sequence">cepp_datas.t_cepp_action_action_id_seq</param>
            </generator>
        </id>
        [....]
        <bag cascade="all-delete-orphan" fetch="select" lazy="true" name="TCeppLignesDeComptes" table="t_cepp_ligne_de_compte">
          <key>
            <column name="action_id" not-null="true"/>
          </key>
          <one-to-many class="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppLigneDeCompte"/>
        </bag>
            [....]
      </class>
    </hibernate-mapping>
    et l'objet B;
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- Generated 25 sept. 2015 09:55:44 by Hibernate Tools 4.3.1 -->
    <hibernate-mapping>
        <class name="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppCompte" table="t_cepp_compte" schema="cepp_datas" optimistic-lock="version">
            <id name="compteId" type="integer" column="compte_id">
                <generator class="sequence">
                    <param name="sequence">cepp_datas.t_cepp_compte_compte_id_seq</param>
                </generator>
            </id>
            <bag fetch="select" cascade="all-delete-orphan" lazy="true" name="TCeppLignesDeCompteSources" table="t_cepp_ligne_de_compte">
              <key>
                <column name="compte_source_id"/>
              </key>
              <one-to-many class="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppLigneDeCompte"/>
            </bag>
            <bag fetch="select" cascade="all-delete-orphan" lazy="true" name="TCeppLignesDeCompteCibles" table="t_cepp_ligne_de_compte">
              <key>
                <column name="compte_cible_id"/>
              </key>
              <one-to-many class="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppLigneDeCompte"/>
            </bag>
        </class>
    </hibernate-mapping>
    Et le mapping de mon objet C :
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- Generated 25 sept. 2015 09:55:44 by Hibernate Tools 4.3.1 -->
    <hibernate-mapping>
      <class name="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppLigneDeCompte" optimistic-lock="version" schema="cepp_datas" table="t_cepp_ligne_de_compte">
        <id column="ligne_de_compte_id" name="ligneDeCompteId" type="integer">
          <generator class="sequence">
            <param name="sequence">cepp_datas.t_cepp_ligne_de_compte_ligne_de_compte_id_seq</param>
          </generator>
        </id>
        <property name="utilisateurId" type="integer">
          <column name="utilisateur_id"/>
        </property>
        <many-to-one class="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppCampagne" fetch="select" name="TCeppCampagne" not-null="true">
          <column name="campagne_id"/>
        </many-to-one>
        <many-to-one class="fr.gouv.agriculture.dal.sial.cepp.entity.TCeppTypeOperation" fetch="select" name="TCeppTypeOperation" not-null="true">
          <column name="type_operation_id"/>
        </many-to-one>
        <property name="compteCibleId" type="integer">
          <column name="compte_cible_id"/>
        </property>
        <property name="compteSourceId" type="integer" not-null="true">
          <column name="compte_source_id"/>
        </property>
        <property name="actionId" type="integer">
          <column name="action_id"/>
        </property>
        <property name="valeur" type="big_decimal">
          <column name="valeur"/>
        </property>
        <property name="actif" type="string">
          <column name="actif"/>
        </property>
        <property name="dateOperation" type="timestamp">
          <column length="29" name="date_operation" not-null="true"/>
        </property>
        <property name="dateModification" type="timestamp">
          <column length="29" name="date_modification"/>
        </property>
      </class>
    </hibernate-mapping>
    Je suis actuellement sur du Java 6 (obligatoire...) et l'utilisation des bag est elle aussi obligatoire.
    A partir du moment ou j'enlève le cascade sur l'entity B (t_cepp_compte), cela fonctionne comme un charme. Le soucis c'est que je veux garder ce cascade car pour d'autres fonctionnalités je dois mettre à jour le compte et ses lignes.

    J'ai vu des pistes comme quoi cela pourrait venir des méthodes hashcode et equals je les ai généré via netbeans en remplaçant les attributs par les getters (à cause du lazy sur le bag).
    cf ce lien what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java

    Mais rien n'y fait. J'ai tenté aussi de clear() le bag de l'objet A(t_cepp_action) au moment de l'update pour ensuite le re-save avec le bag rempli. Même constat. Au moment de flush l'update de l'objet A l'exception est levé.

    Voila, je suis prêt à prendre toutes les pistes pour régler cette erreur !

    Merci d'avance.

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 962
    Par défaut
    Autrement dit, du point de vue conceptuel, vous avez un manytomany entre A et B avec C comme entité intersection, et même plus, car si l'on regarde votre mapping, la table C (ligne de compte) est l'intersection entre 6 tables…

    Dans ce cas-là, il est clairement spécifié dans la doc Hibernate qu'il faut choisir 1 table principale qui aura la responsabilité du cascading,
    dans votre cas le propriétaire principal des "lignes de compte" devrait logiquement être le "compte"

    Vous devez revoir l'analyse technique détaillée pour déterminer dans chaque "use case" quelle est l'entité maître de la logique et vérifier qu'il n'y ait pas de conflit.
    En cas de conflit persistent, vous devrez choisir une solution entre
    - appliquer différents mappings selon le use case car le cascading devra être fait par une entité maître différente (le responsable du cascading),
    - ne garder dans la session que les entités qui sont modifiées par le "use case" et faire un "evict" tôt de celles qui ne sont chargées que pour lire leurs propriétés ce qui peut aussi vous amener à différents mappings, non plus pour changer de "maître" de cascading mais pour ne charger que les champs nécessaires à l'opération (par exemple de ne pas charger le bag C) (autrement dit: avoir un mapping "light" pour certaines situations…)

    Sans oublier d'avoir une stratégie de gestion de ce qui passe si des sessions interactives cohabitent avec le processus batch: au moins vous avez mis en place l'optimistic lock, mais il faudra gérer correctement l'exception pour que l'utilisateur d'un session interactive soit correctement notifié.

  3. #3
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 34
    Par défaut
    Merci de votre réponse et de ces précisions !

    Effectivement il s'agît d'un souci de conception à la base du projet. les fonctionnalités s'étant ajoutées au file de l'eau ont abouti à une architecture un peu hasardeuse.
    La refonte complète du modèle étant à éviter nous avons trouvé un compromis. Un des parents ne cascade qu'en création alors que l'autre est à "all".
    C'est bancale mais dans notre situation cela fonctionne.

    Pour l'optimistic-lock nous avons optimistic-lock="version" sur nos class dans le .hbm

    Pour le evict, j'avais en effet penser décharger les associations dont je n'avais pas besoin pourtant le problème persistait. Même si il n'y avait plus aucun lien entre l'objet A et B (à part C) le cascade plantait.

    En tout cas je prend bonne note de bien vérifier ce genre de cas à l'avenir.

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

Discussions similaires

  1. Réponses: 20
    Dernier message: 13/10/2009, 17h31
  2. Réponses: 0
    Dernier message: 24/10/2008, 14h35
  3. Réponses: 1
    Dernier message: 10/10/2008, 10h39
  4. Réponses: 2
    Dernier message: 03/10/2008, 16h09
  5. [EJB3] Could not execute JDBC batch update
    Par ®om dans le forum JPA
    Réponses: 18
    Dernier message: 07/03/2007, 11h59

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