如何有效地在Hibernate中进行批量更新

时间:2017-10-27 14:49:52

标签: java postgresql hibernate jdbc batch-processing

我阅读了很多文章,并找到了一些批量处理的方法

其中一个是使用flush和clear,以下是代码

        long t1 = System.currentTimeMillis();
        Session session = getSession();
        Transaction transaction = session.beginTransaction();
        try {
            Query query = session.createQuery("FROM PersonEntity WHERE id > " + lastMaxId + " ORDER BY id");
            query.setMaxResults(1000);
            rows = query.list();
            int count = 0;
            if (rows == null || rows.size() == 0) {
                return;
            }
            LOGGER.info("fetched {} rows from db", rows.size());
            for (Object row : rows) {
                PersonEntity personEntity = (PersonEntity) row;
                personEntity.setName(randomAlphaNumeric(30));
                lastMaxId = personEntity.getId();
                session.saveOrUpdate(personEntity);
                if (++count % 50 == 0) {
                    session.flush();
                    session.clear();
                    LOGGER.info("Flushed and Cleared");
                }
            }
        } finally {
            if (session != null && session.isOpen()) {
                LOGGER.info("Closing Session and commiting transaction");
                transaction.commit();
                session.close();
            }
        }
        long t2 = System.currentTimeMillis();
        LOGGER.info("time taken {}s", (t2 - t1) / 1000);

在上面的代码中,我们以1000的批量处理记录并在同一事务中更新它们。

只有我们必须进行批量更新时才可以。

但我有以下问题退出:

  1. 某些其他线程(T2)可能会访问同一组行以进行某些运行时更新操作,但在这种情况下,直到1000批次不会被提交,T2 remians卡住
  2. 那么,我们应该如何处理这个案子呢?

    我可能的想法/解决方案:

    1. 我认为我们可以用50%的小批量在不同的会话中进行更新
    2. 使用不同的无状态连接进行更新并逐个提交传输,但在批量1000完成时关闭会话。
    3. 请帮助我获得更好的解决方案。

1 个答案:

答案 0 :(得分:1)

你的意思是这样说:

  1. 交易中正在进行批量更新

  2. 同时另一个线程开始更新批次中的一条记录

  3. 因此,批次将等到第2点的更新完成。这会导致批处理中的其余记录也等待。 到目前为止,它似乎都很好。然而,重要的是,交易是为了“更快”地更新大量记录。通常,事务用于确保“一致性/原子性”。 如何设计这篇文章 - 一次性快速更新多个记录,原子性不是主要标准,而另一个线程也可能要求更新批次中的记录