prageeth
prageeth

Reputation: 7395

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

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?

Upvotes: 2

Views: 9980

Answers (3)

CODER
CODER

Reputation: 1

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

Upvotes: 0

Suresh Atta
Suresh Atta

Reputation: 122008

You can do something like this

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

Refer Avaoid transaction exception

Upvotes: 1

leewin12
leewin12

Reputation: 1446

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.

Upvotes: 1

Related Questions