Pergunta

há uma solução para o lote inserir através de hibernação na tabela postgresql particionado? Atualmente eu estou recebendo um erro como este ...

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

i ter encontrado neste link http: // listas. jboss.org/pipermail/hibernate-dev/2007-October/002771.html mas não consigo encontrar em qualquer lugar na web é este problema resolvido ou como pode ser a volta

Foi útil?

Solução

Você pode querer tentar usar um Batcher costume, definindo a propriedade hibernate.jdbc.factory_class. Certificar-se de hibernação não irá verificar a contagem de atualização de operações em lote pode resolver o seu problema, você pode conseguir isso, tornando o seu costume Batcher estender a classe BatchingBatcher, e depois substituindo o método doExecuteBatch (...) para se parecer com:

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

        }

    }

Note que o novo método não verifica os resultados da execução das declarações preparadas. Tenha em mente que fazer essa alteração pode afetar de hibernação, de algum modo inesperado (ou talvez não).

Outras dicas

Eles dizem para usar dois gatilhos em uma tabela particionada ou a anotação @SQLInsert aqui: http://www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf páginas 21-26 (também menciona um @SQLInsert especificando um método string).

Aqui está um exemplo com uma depois de gatilho para excluir a linha extra no mestre: https: // gist.github.com/copiousfreetime/59067

Aparece se você pode usar regras em vez de gatilhos para a inserção, em seguida, ele pode retornar o número certo, mas apenas com uma única regra, sem uma declaração WHERE.

ref1

ref2

Reference 3

Outra opção pode ser a criação de uma visão de que 'wraps' da tabela particionada, então você retornar a nova linha para indicar uma atualização da linha de sucesso, sem adicionar acidentalmente uma linha extra indesejada a tabela mestre.

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

Se você foi a visão invólucro rota uma opção é também definem trivial "em vez de" gatilhos para exclusão e atualização, bem, então você pode apenas usar o nome da tabela de visão no lugar de sua tabela normal em todas as transações .

Outra opção que utiliza a vista é criar uma regra de inserção para que quaisquer inserções na tabela principal Ir para a visão [que usa seu gatilho], ex (supondo que você já tem partitioned_insert_trigger e tablename_view e insert_view_trigger criado como listado acima)

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

Em seguida, ele irá usar a sua nova pastilha vista de trabalho wrapper.

thnx! que fez o truque, sem problemas poped, até agora:) .... uma coisa tu ... i teve que implementar classe BatcherFactory e colocá-lo int o arquivo persistence.xml, assim:

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

desde que a fábrica Chamei minha implementação batcher com o código acima

ps hibernate núcleo 3.2.6 GA

Obrigado mais uma vez

I enfrentou o mesmo problema ao inserir documentos através de hibernação depois de muita pesquisa encontrou que ele está esperando que linhas atualizadas deve ser devolvido então ao invés de variação nula para novo no procedimento de gatilho que vai resolver o problema, como mostrado abaixo

RETURN NEW

Eu encontrei outra solução para o mesmo problema nesta página :

Isto sugere a mesma solução que @rogerdpack disse, mudando o retornar NULL para Voltar NEW , e adicionando um novo gatilho que exclui o tuple duplicado no mestre com o consulta:

DELETE FROM ONLY master_table;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top