使用constraintviolationexception进行Hibernate批量更新

时间:2011-11-15 15:14:54

标签: hibernate constraints

我正在批量更新大量对象,并且想要忽略任何重复项。 这样做的最佳方式是什么?

我的理解是,如果抛出ConstrainViolationException,则批次中的所有其他对象将 NOT 保持不变。

2 个答案:

答案 0 :(得分:2)

这是我的解决方案:

    private void saveBatch() {
    StatelessSession session = sessionFactory.openStatelessSession();
    Transaction tx = session.beginTransaction();

    try {
        for (Object t : batchList) {
            session.insert(t);
        }
        tx.commit();
    } catch (ConstraintViolationException e) {

        log.info("Duplicate in batch...save individually");
        tx.rollback();
        session.close();
        saveIndividually();
        return;
    }

    session.close();
    batchList.clear();
}

private void saveIndividually() {
    StatelessSession session = sessionFactory.openStatelessSession();
    for (Object t : batchList) {
        Transaction tx = session.beginTransaction();
        session.insert(t);
        try {
            tx.commit();
        } catch (ConstraintViolationException e) {
            tx.rollback();
            log.warn("Ignoring duplicate: " + t);
        }

    }

    session.close();
    batchList.clear();
}

答案 1 :(得分:0)

确保一致性的一种方法是确保所有实体'关联具有正确的级联选项配置(例如,如果您希望某个实体在持久化时也会保留其关联中包含的任何新关联实体,则应配置cascade =" save-update")。

如果您不能/不能这样做,理论上的替代方法是为您的每个批处理操作创建一个单独的事务(如每个实体插入),如果该事务滚动由于异常而退回,您捕获异常并继续(可能保留失败事务的缓存以便稍后重试)。然而,这很可能不实用,因为与在一个事务中执行所有操作(真正的批量更新)相比,处理所需的时间要长很多。

就个人而言,当我遇到这种情况时,我会通过JDBC进行批处理操作(使用Hibernate架构,并确保生成相同的序列)。通过这种方式,它更快,您无法更准确地处理此类问题。