StaleObjectStateException with generated ID

Hello Hibernate People,

I get a StaleObjectStateException when the mapping of a class contains in ID with a generator class SequenceStyleGenerator. When I remove the from the ID and set the ID programmatically it works.

Here the mapping definition of the ID:

<class name="BankAccount" table="KP_CREDITACCOUNT">
    <id name="bankAccountId"
        column="CREDITACCOUNTID"
        type="java.lang.Long"
        access="field">
        <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
            <param name="sequence_name">KP_SEQUENCE_BANKACCOUNT</param>
        </generator>
    </id>
    ...
</class>

The exception occurs, when the code tries to delete a GuaranteeCreditAccount entity, which is a subclass of BankAccount from the database, but the entity doesn’t exist anymore, because it has been previously deleted because of a cascaded database delete:

Caused by: javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [de.bayernlb.kundenportal.businessclasses.bankaccount.GuaranteeCreditAccount#4711]
	at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:226)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:93)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1489)
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:514)
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3353)
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2525)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
	at de.bayernlb.kundenportal.persistence.TransactionContext.commitTransaction(TransactionContext.java:66)
	... 27 more
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [de.bayernlb.kundenportal.businessclasses.bankaccount.GuaranteeCreditAccount#4711]
	at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2529)
	at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3364)
	at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3238)
	at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3639)
	at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:146)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1483)
	... 36 more

The SQL trace in this situation looks like this:

Hibernate: select businesspa_.BIZPARTNERID, businesspa_.BIZPARTNERNAME as BIZPARTNERNAME2_0_ from KP_BIZPARTNER businesspa_ where businesspa_.BIZPARTNERID=?
Hibernate: update KP_CREDITACCOUNT set ACCOUNTNUMBER=?, CREDITACCOUNTTYPE=?, BIZPARTNERID=?, BASENUMBER=?, CURRENCY_=?, CURRENCYEXCHANGERATE=?, INTERESTRATE=?, BALANCE=?, SUBNUMBER=?, EXPIRATIONDATE=?, GUARANTEECREDITTYPE=?, REFERENCENUMBER=?, SORTCRITERIA=?, CREDITLIMIT=?, COMMISSIONRATE=? where CREDITACCOUNTID=?

The first select statement returns an empty result, because the entity doesn’t exist anymore. The reason for the second update statement is unclear for me. Normally a delete statement should be executed here to delete the entity from the KP_CREDITACCOUNT table.

When I remove the from the ID mapping the SQL trace looks like this:

Hibernate: select guaranteec_.CREDITACCOUNTID, guaranteec_.ACCOUNTNUMBER as ACCOUNTNUMBER2_1_, guaranteec_.CREDITACCOUNTTYPE as CREDITACCOUNTTYPE3_1_, guaranteec_.BIZPARTNERID as BIZPARTNERID4_1_, guaranteec_.BASENUMBER as BASENUMBER5_1_, guaranteec_.CURRENCY_ as CURRENCY_6_1_, guaranteec_.CURRENCYEXCHANGERATE as CURRENCYEXCHANGERA7_1_, guaranteec_.INTERESTRATE as INTERESTRATE8_1_, guaranteec_.BALANCE as BALANCE9_1_, guaranteec_.SUBNUMBER as SUBNUMBER10_1_, guaranteec_.EXPIRATIONDATE as EXPIRATIONDATE11_1_, guaranteec_.GUARANTEECREDITTYPE as GUARANTEECREDITTY12_1_, guaranteec_.REFERENCENUMBER as REFERENCENUMBER13_1_, guaranteec_.SORTCRITERIA as SORTCRITERIA14_1_, guaranteec_.CREDITLIMIT as CREDITLIMIT15_1_, guaranteec_.COMMISSIONRATE as COMMISSIONRATE16_1_ from KP_CREDITACCOUNT guaranteec_ where guaranteec_.CREDITACCOUNTID=?
Mär 17, 2020 5:24:12 PM org.hibernate.event.internal.DefaultDeleteEventListener deleteTransientEntity
INFO: HHH000114: Handling transient entity in delete processing

The select statement returns an empty result and hibernate seems to recognize that the entity is already deleted and does nothing, which is the expected behaviour.

Can someone explain the difference here and how to fix it with the . Off course we need the generated ID and cannot create the ID in code.

We use Hibernate version 5.4.3 and an Oracle 10g database.

Kind regards
Thomas Mayr