Recover Hibernate Session State After Failed Insertion

The following code tries to insert an Item object in db using Spring + Hibernate. An element has an Integer id field as a primary key, as well as a name column that obeys a unique constraint (simplified example).
I know that the element identifier is null (the element is temporary), however the insertion may still fail due to the unique restriction in the name field.

 try { getHibernateTemplate().save(myItem); getHibernateTemplate().flush(); // exception thrown here if the name is not unique } catch (DataIntegrityViolationException e) { Item itemFromDb = (Item) getHibernateTemplate() .find("from Item item where item.name = ?", myItem.getName()).get(0); // // copy some properties from myItem to itemFromDb // getHibernateTemplate.update (itemFromDb) } 

I need this code to run in a loop for many elements, all in one transaction, so I am trying to release an update if the insertion does not work.

However, after the insert failed, the hibernate session is in a weird state, and when I issue a select statement to get the element from db, an original exception is thrown.

I tried using session.evict() after the insert failed, but to no avail. Any idea?

This is what I see on the console after the selection. Hibernate does not work in the select statement, but still prints information about the previous insert statement.

 WARN [http-8080-1] hibernate.util.JDBCExceptionReporter (JDBCExceptionReporter.java:77) - SQL Error: 2627, SQLState: 23000 ERROR [http-8080-1] hibernate.util.JDBCExceptionReporter (JDBCExceptionReporter.java:78) - Violation of UNIQUE KEY constraint 'unq_Item_name'. Cannot insert duplicate key in object 'items'. ERROR [http-8080-1] event.def.AbstractFlushingEventListener (AbstractFlushingEventListener.java:301) - Could not synchronize database state with session org.hibernate.exception.ConstraintViolationException: could not insert: [com.sample.Item] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71) 

PS please don't tell me about saveOrUpdate sleep mode, I know what it does.

+4
source share
2 answers

Hibernate does not guarantee anything about a session when a database exception is thrown. You have to roll back. If I understand the sentence of Bojo, he says that you must first read from the column of the name to make sure that the insert does not fail. It makes sense to me.

+3
source
 getHibernateTemplate().merge(myItem); 

merge - copy the state of this object to a permanent object with the same identifier. If there is no persistent instance in the session, it will be loaded. Return the persistent instance. If this instance is incorrect, save a copy and return it as a new permanent instance. This instance is not associated with a session. This operation cascades to related instances if the association maps to cascade = "merge".

+1
source

Source: https://habr.com/ru/post/1301588/


All Articles