【问题标题】:In batch insert, how to continue inserting other rows when an error occurred in one row批量插入时,某一行出错时如何继续插入其他行
【发布时间】:2013-02-16 16:20:58
【问题描述】:

在我的代码中,我正在执行批量插入。例如,认为我有五行要插入,其中一个在插入时失败。然后休眠防止插入所有行。
就我而言,我想插入其他四个不包含错误的记录。这在 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()方法?

【问题讨论】:

    标签: hibernate batch-processing


    【解决方案1】:

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

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

    看看这个文档transactions-demarcation-exceptions

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

    【讨论】:

    • 谢谢@dgregory。我修改了我的代码,请查看我修改后的问题。
    【解决方案2】:

    你可以这样做

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

    参考Avaoid transaction exception

    【讨论】:

    • 感谢@The Suresh Atta。我修改了我的代码,请查看我修改后的问题。
    • No 当事务提交时不需要调用会话刷新。
    • 感谢苏雷什的帮助。
    【解决方案3】:

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

    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;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-19
      • 2018-10-13
      • 1970-01-01
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多