hibernate使用分区的postgresql插入批处理

hibernate postgresql insert database-partitioning

7926 观看

7回复

869 作者的声誉

是否有分区postgresql表中通过hibernate批量插入的解决方案?目前我收到这样的错误......

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但我在网上找不到任何地方这个问题已解决或如何解决

作者: tropikalista 的来源 发布者: 2008 年 9 月 17 日

回应 (7)


4

191 作者的声誉

决定

您可能希望通过设置hibernate.jdbc.factory_class属性来尝试使用自定义Batcher。确保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;
            }

        }

    }

请注意,新方法不会检查执行预准备语句的结果。请记住,进行此更改可能会以某种意外方式(或可能不会)影响休眠。

作者: alexguev 发布者: 18.09.2008 04:31

2

869 作者的声誉

日Thnx!它做了诀窍,没有任何问题加速,到目前为止:)....有一件事你...我必须实现BatcherFactory类并将其放在persistence.xml文件中,如下所示:

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

从那个工厂我用上面的代码调用了我的batcher实现

ps hibernate core 3.2.6 GA

再次感谢

作者: tropikalista 发布者: 18.09.2008 12:22

2

7858 作者的声誉

他们说在分区表中使用两个触发器或在这里使用@SQLInsert注释:http//www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf第21-26页(它还提到了指定字符串的@SQLInsert方法)。

下面是一个使用after触发器来删除master中额外行的示例:https//gist.github.com/copiousfreetime/59067

作者: Piotr Gwiazda 发布者: 25.05.2010 02:05

2

32971 作者的声誉

如果您可以使用RULES而不是插入触发器,则它会出现,然后它可以返回正确的数字,但只能使用没有WHERE语句的单个RULE。

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

参考: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.*);

然后它将使用您的新工作视图包装器插入。

作者: rogerdpack 发布者: 30.09.2014 02:45

0

1 作者的声誉

我在遇到大量搜索后通过hibernate插入文件时遇到了同样的问题,发现它应该返回更新的行,而不是null将其更改为触发器过程中的new,这将解决问题,如下所示

返回新的

作者: Arun Kumar V 发布者: 02.05.2017 06:16

0

1 作者的声誉

在这个网页上找到了针对同一问题的另一种解决方案:

这表明@rogerdpack说的相同解决方案,将Return Null更改为Return NEW,并添加一个新的触发器,用查询删除master中的重复元组:

DELETE FROM ONLY master_table;
作者: blov80 发布者: 03.10.2018 12:57

-1

19 作者的声誉

由于我没有权限评论我在这里发布的帖子...

@Adil B,

如果您在插入触发器之后使用只有主表的删除操作后遇到任何性能问题,请告诉我。我正在考虑实施这个解决方案,只是想知道是否会有任何性能下降?

作者: Sandy007 发布者: 09.11.2018 08:39
32x32