Пакет вставки спящего режима с разделенным postgresql

есть ли решение для пакетной вставки через спящий режим в секционированной таблице 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, но я не могу найти нигде в Интернете, эта проблема решена или как это может быть обойти

Ответ 1

Возможно, вы захотите попробовать использовать пользовательский дозатор, установив свойство hibernate.jdbc.factory_class. Убедившись, что спящий режим не будет проверять количество обновлений пакетных операций, может устранить вашу проблему, вы можете добиться этого, сделав свой пользовательский дозатор расширением класса 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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

ref1

ref2

ref3

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

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

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

Другим вариантом, использующим представление, является создание правила вставки, чтобы любые вставки в главной таблице переходили к представлению [которое использует его триггер], ex (если у вас уже есть 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.*);

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

Ответ 5

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

ВОЗВРАТ НОВЫЙ