Domanda

esiste una soluzione per l'inserimento batch tramite ibernazione nella tabella postgresql partizionata?attualmente ricevo un errore come questo...

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)....

ho trovato questo collegamento http://lists.jboss.org/pipermail/hibernate-dev/2007-October/002771.html ma non riesco a trovare da nessuna parte sul Web se questo problema è stato risolto o come aggirarlo

È stato utile?

Soluzione

Potresti provare a utilizzare un Batcher personalizzato impostando la proprietà hibernate.jdbc.factory_class.Assicurandoti che l'ibernazione non controlli il conteggio degli aggiornamenti delle operazioni batch potrebbe risolvere il tuo problema, puoi farlo facendo in modo che il tuo Batcher personalizzato estenda la classe BatchingBatcher e quindi sovrascrivendo il metodo doExecuteBatch(...) per assomigliare a:

    @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;
            }

        }

    }

Tieni presente che il nuovo metodo non controlla i risultati dell'esecuzione delle istruzioni preparate.Tieni presente che apportare questa modifica potrebbe influire sull'ibernazione in qualche modo inaspettato (o forse no).

Altri suggerimenti

Dicono di utilizzare due trigger in una tabella partizionata o l'annotazione @SQLInsert qui: http://www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf pagine 21-26 (menziona anche un @SQLInsert che specifica un metodo String).

Ecco un esempio con un trigger after per eliminare la riga aggiuntiva nel master: https://gist.github.com/copiousfreetime/59067

Appare se è possibile utilizzare RULES invece di trigger per l'inserimento, quindi può restituire il numero corretto, ma solo con una singola RULE senza un'istruzione WHERE.

rif1

rif2

rif3

un'altra opzione potrebbe essere quella di creare una vista che "racchiuda" la tabella partizionata, quindi restituire la NUOVA riga per indicare un aggiornamento della riga riuscito, senza aggiungere accidentalmente una riga aggiuntiva indesiderata alla tabella principale.

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

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

Se hai seguito il percorso del wrapper di visualizzazione, un'opzione è anche definire banali trigger "invece di" per l'eliminazione e l'aggiornamento, quindi puoi semplicemente utilizzare il nome della tabella di visualizzazione al posto della tabella normale in tutte le transazioni.

Un'altra opzione che utilizza la vista è creare una regola di inserimento in modo che qualsiasi inserimento sulla tabella principale vada alla vista [che usa il suo trigger], es (supponendo che tu abbia già partitioned_insert_trigger e tablename_view e insert_view_trigger creati come elencato sopra)

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

Quindi utilizzerà il nuovo inserto wrapper della vista di lavoro.

grazie!ha funzionato, finora non si è verificato alcun problema :)....una cosa tu...ho dovuto implementare BatcherFactory class e inseriscilo in persistence.xml file, come questo:

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

da quella fabbrica ho chiamato la mia implementazione batcher con il codice sopra

PS Hibernate Core 3.2.6 GA

grazie ancora

Ho riscontrato lo stesso problema durante l'inserimento di documenti tramite l'ibernazione dopo che molte ricerche hanno scoperto che si prevede che vengano restituite le righe aggiornate, quindi invece di null cambiarlo in una nuova procedura di trigger che risolverà il problema come mostrato di seguito

RITORNO NUOVO

Ho trovato un'altra soluzione per lo stesso problema su questa pagina web:

Ciò suggerisce la stessa soluzione detta da @rogerdpack, modificando il file Restituisce Null A Ritorno NUOVO, e aggiungendo un nuovo trigger che elimina la tupla duplicata nel master con la query:

DELETE FROM ONLY master_table;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top