Пакет вставки спящего режима с разделенным 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 в триггерной процедуре, которая разрешит проблему, как показано ниже.
ВОЗВРАТ НОВЫЙ