在批处理插入中,如何在一行中发生错误时继续插入其他行

时间:2013-03-02 02:35:27

标签: hibernate batch-processing

在我的代码中,我正在进行批量插入。例如,我想要插入五行,其中一行在插入时失败。然后休眠防止插入所有行。
在我的情况下,我想插入其他四个没有错误的记录。这可能在Hibernate中吗?
以下是我的代码的简化版本。

void save() {
  Session session1 = HibernateUtil.getSessionFactory().openSession();
  Transaction transaction = session1.beginTransaction();

  for (int i = 0; i < 5; i++) {
    BatchSizeConf r = new BatchSizeConf();//This is my entity
    r.setId(i);
    r.setDispatchType("Disp");
    r.setBatchSize(500);
    Serializable z = session1.save(r);
    System.out.println(z);//prints ids
  }

  session1.flush();
  session1.clear();
  session1.getTransaction().commit();
  session1.close();
}

修改

<小时/> 根据下面的答案,我改变了我的代码并解决了我的主要问题。现在我的代码是这样的。

void save() {
  for (int i = 0; i < 5; i++) {
    Session session1 = HibernateUtil.getSessionFactory().openSession();
    Transaction transaction = session1.beginTransaction();

    BatchSizeConf r = new BatchSizeConf();//This is my entity
    r.setId(i);
    r.setDispatchType("Disp");
    r.setBatchSize(500);

    try {
      session1.save(r);
      transaction.commit();
    } catch (HibernateException e) {
      System.out.println("Failed: " + i);
    }

    session1.flush();
    session1.clear();
    session1.close();
  }
}

我现在还有两个问题。

  1. 是否可以像上面那样创建多个会话对象? (我有超过100000条记录。)
  2. 我是否需要按上述方式拨打flush()clear()close()方法?

3 个答案:

答案 0 :(得分:1)

这是不可能的,事务将被任何异常标记为回滚。

为什么不将行分成块并为每个块设置单个事务?

查看此文档transactions-demarcation-exceptions

  

如果Session抛出异常(包括任何SQLException),则立即回滚数据库事务,调用Session.close()并丢弃Session实例。 Session的某些方法不会使会话保持一致状态。 Hibernate抛出的异常都不能被视为可恢复的。确保通过在finally块中调用close()来关闭Session。

答案 1 :(得分:1)

你可以做这样的事情

Transaction tx = session.beginTransaction();
...
for (BatchSizeConf  b: BatchSizeConfList) {
    ...
    tx.commit();
}

参考Avaoid transaction exception

答案 2 :(得分:0)

是..我们可以做..请参阅此代码。

public List<RecordErrorStatus> persistBatch(ArrayList<?> domainRecords) {

        List<RecordErrorStatus> fedRecordErrorStatusList = new ArrayList<RecordErrorStatus>();
        Session session = getSession();
        Transaction tx = session.beginTransaction();
        long rowCount = 0;
        boolean insertionFailed=false;
        for (Object object : domainRecords) {
            rowCount++;
            try {
                System.out.println("Inserting Record:"+rowCount+object);
                session.persist(object); // Persist the given transient instance
                if (! this.rollBackOnFail) {
                    tx.commit();
                    tx = session.beginTransaction();
                }
            } catch (Exception e) {
                e.printStackTrace();
                RecordErrorStatus feedRecordStatus = new RecordErrorStatus();
                feedRecordStatus.setRowNumber(String.valueOf(rowCount));
                StringWriter sw = new StringWriter();
                e.printStackTrace(new PrintWriter(sw));
                String exceptionAsString = sw.toString();
                feedRecordStatus.setErrorDescription(exceptionAsString);
                fedRecordErrorStatusList.add(feedRecordStatus);
                insertionFailed =true;
                tx.rollback(); //Rollback the current record..
                session.clear();//Clear the seesion.. If not, throws Nested Transaction not allowd...
                tx = session.beginTransaction();//Start again..
            } 
        }
        if (this.rollBackOnFail && insertionFailed && ! tx.wasRolledBack()) {
            tx.rollback();
            System.out.println("Rollback");
        } 
        return fedRecordErrorStatusList;
    }