Reputation: 7395
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:
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.
flush()
, clear()
and close()
methods as above?Upvotes: 2
Views: 9980
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
Reputation: 122008
You can do something like this
Transaction tx = session.beginTransaction();
...
for (BatchSizeConf b: BatchSizeConfList) {
...
tx.commit();
}
Refer Avaoid transaction exception
Upvotes: 1
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