Question

existe-t-il une solution pour l'insertion de lot via hibernation dans la table postgresql partitionnée? actuellement, je reçois une erreur comme celle-ci ...

ERROR org.hibernate.jdbc.AbstractBatcher - Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
   at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
   at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
   at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:68)....

J'ai trouvé ce lien http: // listes. jboss.org/pipermail/hibernate-dev/2007-October/002771.html mais je ne trouve nulle part sur le Web ce problème qui a été résolu ou comment il peut être contourné

Était-ce utile?

La solution

Vous pouvez utiliser un Batcher personnalisé en définissant la propriété hibernate.jdbc.factory_class. Assurez-vous que hibernate ne vérifie pas le nombre de mises à jour des opérations par lot afin de résoudre votre problème. Vous pouvez y parvenir en faisant en sorte que votre Batcher personnalisé étende la classe BatchingBatcher, puis remplace la méthode doExecuteBatch (...) par:

    @Override
    protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException {
        if ( batchSize == 0 ) {
            log.debug( "no batched statements to execute" );
        }
        else {
            if ( log.isDebugEnabled() ) {
                log.debug( "Executing batch size: " + batchSize );
            }

            try {
//              checkRowCounts( ps.executeBatch(), ps );
                ps.executeBatch();
            }
            catch (RuntimeException re) {
                log.error( "Exception executing batch: ", re );
                throw re;
            }
            finally {
                batchSize = 0;
            }

        }

    }

Notez que la nouvelle méthode ne vérifie pas les résultats de l'exécution des instructions préparées. N'oubliez pas que ce changement peut avoir un effet inattendu (ou non) sur l'hibernation.

Autres conseils

Ils recommandent d'utiliser deux déclencheurs dans une table partitionnée ou l'annotation @SQLInsert ici: http://www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf pages 21-26 (il mentionne également un @SQLInsert spécifiant une méthode String).

Voici un exemple avec un déclencheur après qui supprime la ligne supplémentaire dans le maître: https: // gist.github.com/copiousfreetime/59067

Apparaît si vous pouvez utiliser RULES au lieu de déclencheurs pour l'insertion, il peut alors renvoyer le nombre correct, mais uniquement avec une seule règle sans instruction WHERE.

ref1

ref2

ref3

une autre option consiste à créer une vue qui "enveloppe" la table partitionnée, puis vous renvoyez la ligne NEW pour indiquer que la mise à jour de la ligne a été effectuée avec succès, sans ajouter accidentellement une ligne supplémentaire non souhaitée à la table maître.

create view tablename_view as select * from tablename; -- create trivial wrapping view

CREATE OR REPLACE FUNCTION partitioned_insert_trigger() -- partitioned insert trigger
RETURNS TRIGGER AS $
BEGIN
   IF (NEW.partition_key>= 5500000000 AND
       NEW.partition_key <  6000000000) THEN
      INSERT INTO tablename_55_59 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 5000000000 AND
          NEW.partition_key <  5500000000) THEN
      INSERT INTO tablename_50_54 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 500000000 AND
          NEW.partition_key  <  1000000000) THEN
      INSERT INTO tablename_5_9 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 0 AND
          NEW.partition_key <  500000000) THEN
      INSERT INTO tablename_0_4 VALUES (NEW.*);
   ELSE
      RAISE EXCEPTION 'partition key is out of range.  Fix the trigger function';
   END IF;
   RETURN NEW; -- RETURN NEW in this case, typically you'd return NULL from this trigger, but for views we return NEW
END;
$
LANGUAGE plpgsql;

CREATE TRIGGER insert_view_trigger
   INSTEAD OF INSERT ON tablename_view
   FOR EACH ROW EXECUTE PROCEDURE partitioned_insert_trigger(); -- create "INSTEAD OF" trigger

ref: http://www.postgresql.org/docs/ 9.2 / static / trigger-definition.html

Si vous avez choisi la route de l’affichage des vues, une option consiste également à définir un " trivial au lieu de " déclencheurs de suppression et de mise à jour, vous pouvez simplement utiliser le nom de la table de vue à la place de votre table normale dans toutes les transactions.

Une autre option qui utilise la vue consiste à créer une règle d'insertion afin que toutes les insertions de la table principale soient placées dans la vue [qui utilise son déclencheur], par exemple (en supposant que vous ayez déjà partitioned_insert_trigger et tablename et insert_view_trigger créé comme indiqué ci-dessus)

create RULE use_right_inserter_tablename AS
      ON INSERT TO tablename
      DO INSTEAD insert into tablename_view VALUES (NEW.*);

Ensuite, il utilisera votre nouvel insert de wrapper de vue de travail.

thnx! ça a fait l'affaire, aucun problème n'a surgi jusqu'à présent:) .... une chose que tu ... Je devais implémenter la classe BatcherFactory et la mettre dans le fichier persistence.xml , comme ceci:

property name="hibernate.jdbc.factory_class" value="path.to.my.batcher.factory.implementation"

de cette usine, j'ai appelé mon implémentation Batcher avec le code ci-dessus

ps mettre en veille 3.2.6 GA

merci encore une fois

J'ai rencontré le même problème lors de l'insertion de documents dans hibernate après que de nombreuses recherches aient révélé qu'il s'attendait à ce que les lignes mises à jour soient renvoyées. >

RETOUR NOUVEAU

J'ai trouvé une autre solution au même problème sur cette page Web :

Ceci suggère la même solution que celle indiquée par @rogerdpack, en remplaçant Renvoyer Null par Renvoyer NOUVEAU , et en ajoutant un nouveau déclencheur qui supprime le tuple dupliqué dans le maître avec requête:

DELETE FROM ONLY master_table;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top