пакет вставки hibernate с разделенным postgresql - PullRequest
11 голосов
/ 17 сентября 2008

Есть ли решение для пакетной вставки через Hibernate в многораздельной таблице postgresql? в настоящее время я получаю сообщение об ошибке, как это ...

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

Я нашел эту ссылку http://lists.jboss.org/pipermail/hibernate-dev/2007-October/002771.html, но нигде не могу найти в Интернете, решена ли эта проблема или как ее обойти

Ответы [ 6 ]

4 голосов
/ 18 сентября 2008

Возможно, вы захотите попробовать использовать пользовательский дозатор, установив свойство hibernate.jdbc.factory_class. Убедившись, что hibernate не будет проверять количество обновлений пакетных операций, может решить вашу проблему, вы можете добиться этого, сделав свой собственный Batcher расширенным классом BatchingBatcher, а затем переопределив метод doExecuteBatch (...), чтобы он выглядел так:

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

        }

    }

Обратите внимание, что новый метод не проверяет результаты выполнения подготовленных операторов. Имейте в виду, что внесение этого изменения может неожиданно повлиять на режим гибернации (или, возможно, нет).

2 голосов
/ 30 сентября 2014

Появляется, если вы можете использовать ПРАВИЛА вместо триггеров для вставки, тогда он может вернуть правильное число, но только с одним ПРАВИЛОМ без оператора WHERE.

ref1

ref2

REF3

другой вариант может заключаться в создании представления, которое «оборачивает» секционированную таблицу, после чего вы возвращаете строку NEW, чтобы указать на успешное обновление строки, без случайного добавления дополнительной нежелательной строки в основную таблицу.

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

Если вы пошли по маршруту оболочки представления, один из вариантов также определить тривиальные триггеры «вместо» для удаления и обновления, а затем вы можете просто использовать имя таблицы представления вместо обычной таблицы во всех транзакциях. .

Другой вариант, использующий представление, - это создание правила вставки, чтобы любые вставки в основной таблице переходили в представление [которое использует его триггер], например (при условии, что у вас уже есть partitioned_insert_trigger, а tablename_view и insert_view_trigger созданы как указано в списке). выше)

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

Тогда он будет использовать вашу новую рабочую вставку для представления.

2 голосов
/ 25 мая 2010

Они говорят, что используют два триггера в секционированной таблице или аннотацию @SQLInsert здесь: http://www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf страницы 21-26 (здесь также упоминается @SQLInsert, указывающий метод String).

Вот пример с последующим триггером для удаления дополнительной строки в мастере: https://gist.github.com/copiousfreetime/59067

2 голосов
/ 18 сентября 2008

Thnx! он сделал свое дело, никаких проблем не всплыло, пока:) .... одно ты ... мне пришлось реализовать класс BatcherFactory и поместить его в файл persistence.xml, как это:

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

с этой фабрики я назвал свою реализацию дозатора с кодом выше

п.с. спящий ядро ​​3.2.6 GA

еще раз спасибо

0 голосов
/ 03 октября 2018

Я нашел другое решение для той же проблемы на этой веб-странице :

Это предлагает то же решение, которое сказал @rogerdpack, изменив Return Null на Return NEW и добавив новый триггер, удаляющий дублированный кортеж в мастере с запросом:

DELETE FROM ONLY master_table;
0 голосов
/ 02 мая 2017

Я столкнулся с той же проблемой, когда вставлял документы в режиме гибернации, после того, как во время поиска было обнаружено, что он ожидает, что обновленные строки должны быть возвращены, поэтому вместо нуля измените его на новый в триггерной процедуре, которая решит проблему, как показано ниже

ВОЗВРАТ НОВОГО

...