In batch insert, how to continue inserting other rows when an error occurred in one row

丶灬走出姿态 提交于 2019-12-08 00:14:57

问题


In my code I am doing a batch insert. For an example think that I have five rows to insert, and one of those fails when inserting. Then hibernate prevent inserting all the rows.
In my case I want to insert other four records which contains no errors. Is this possible in Hibernate?
Following is a simplified version of my code.

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

EDIT:


According to following answers below I changed my code and solved my main problem. Now my code is like this.
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();
  }
}

I Now I have another two questions.

  1. Is it ok to create multiple session objects like above? (I have more than 100000 records.)
  2. Do I need to call flush(), clear() and close() methods as above?

回答1:


You can do something like this

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

Refer Avaoid transaction exception




回答2:


That's not possible, transaction will be marked as rollback by any exception.

Why don't chipped rows into chunks and set single transaction per each chunk?

Take a look this docs transactions-demarcation-exceptions

If the Session throws an exception, including any SQLException, immediately rollback the database transaction, call Session.close() and discard the Session instance. Certain methods of Session will not leave the session in a consistent state. No exception thrown by Hibernate can be treated as recoverable. Ensure that the Session will be closed by calling close() in a finally block.




回答3:


Yes.. We can do.. See this code.

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



来源:https://stackoverflow.com/questions/15170049/in-batch-insert-how-to-continue-inserting-other-rows-when-an-error-occurred-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!