Reputation: 31020
Sometimes when persisting an obj, one of its field is too large to fit into the db field, resulting in a data truncation exception. In the following code, I attempt to catch the DataException and simply empty out the field, and the resave. However I get an exception when resaving. Why does the Batch update exception occur and how do I get around it?
public static void save(Object obj) throws Exception{ try{ beginTransaction(); getSession().save(obj); commitTransaction(); }catch(Exception e){ e.printStackTrace(); rollbackTransaction(); throw e; }finally{ closeSession(); //not needed, session obtained from sf.getCurrentSession() will auto close } } public static void saveXXX(XXX rec){ try { save(rec); } catch (org.hibernate.exception.DataException e) { e.printStackTrace(); saveXXX(rec, e); //causes an exception } catch (Exception e) { e.printStackTrace(); } } private static void saveXXX(WhoisRecord rec, DataException e) { rec.setField(""); //empty out the problem field saveXXX(rec);
Exception:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85) at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114) at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109) at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2382) at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137) . . .
Upvotes: 6
Views: 21870
Reputation: 2922
what i have experienced is that this exception raise when updating object have an id which not exist in table. if you read exception message it says "Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1" which means it was unable to found record with your given id.
To avoid this i always read record with same id if i found record back then i call update otherwise throw "exception record not found".
Upvotes: 1
Reputation: 11
That comes from your mapping file. The native generator class maps to a sequence in Oracle. Either create the sequence (don't know the base name which it used but I guess it is in the hibernate docs) or switch to another generator.
I change from native to assigned, and now it don't get any exception but , the object is not persisted in the data base.
http://forum.spring.io/forum/spring-projects/data/19856-not-saving-in-an-oracle-data-base
Upvotes: 1
Reputation: 5293
I got this error because I had the wrong generator of the key in the class mapping, and then I did an insert first and an update later in the same transaction.
The key column was defined as autoincrement (in MySQL), and with this mapping
<id name="tableId" type="long" access="field">
<column name="tableId" />
<generator class="assigned" />
</id>
I got a StaleStateException, but when I corrected the entry to
<id name="tableId" type="long" access="field">
<column name="tableId" />
<generator class="native" />
</id>
then it worked well without problems.
Upvotes: 3
Reputation: 985
I'm no expert on this, but I think I just had the same problem but in the opposite direction.
It looks like what's happening is that you try to save the record, and Hibernate throws that data truncation exception, meaning it saved something but not all of what you wanted. So you catch that exception, and try to roll back the transaction. But this isn't always guaranteed to succeed (from what I see on Hibernate save() and transaction rollback), so the saved data could still be there. Let's assume it is. Next you alter your record, and try to save it again.
But since the data is still there, calling save won't do anything, as in that case it should be an update. So when you try to commit that transaction, Hibernate knows that you want to save the 1 record but it succeeds in saving 0, hence the error.
Try changing getSession().save(obj); to getSession().saveOrUpdate(obj);. That should save the record when it doesn't exist and update it (to not have the overlarge field) when it does.
Upvotes: 3
Reputation: 5707
I have not enough clues to tell you exactly. I can just say I had the same issue and solved by calling merge() instead of save(). You should always use merge() in case if detached objects.
Upvotes: 2