what about adding a catch(ObjectNotFoundException onfe){ pe = new OptimisticLockException( e.getMessage, e); } to the existing try/catch that encloses the entity = sharedSessionContract.load( sose.getEntityName(), identifier ) ?
On 17 May 2016 at 13:32, Vlad Mihalcea <mihalcea.v...@gmail.com> wrote: > Hi, > > While fixing tests for Oracle after rebasing my branch, I realized that the > org.hibernate.test.optlock.OptimisticLockTest > testOptimisticLockAllDelete > fails on Oracle10gDialect, while running just fine on H2. > > When reaching the following branching logic in AbstractEntityPersister: > > if ( useBatch ) { > session.getJdbcCoordinator().getBatch( deleteBatchKey ).addToBatch(); > } > else { > check( > > session.getJdbcCoordinator().getResultSetReturn().executeUpdate( delete ), > id, > j, > expectation, > delete > ); > } > > If using H2, we go to the useBatch branch, while for Oracle dialects that > are less than 12c (hibernate.jdbc.batch_versioned_data is set to false, > therefore JDBC batching is disabled) it goes on the second branch logic. > > This way, for H2, a StaleStateException is thrown and the flush operation > flow is disrupted. > > For Oracle, the check method call will throw a StaleObjectStateException > instead: > > catch (StaleStateException e) { > if ( !isNullableTable( tableNumber ) ) { > if ( getFactory().getStatistics().isStatisticsEnabled() ) { > getFactory().getStatisticsImplementor() > .optimisticFailure( getEntityName() ); > } > throw new StaleObjectStateException( getEntityName(), id ); > } > return false; > } > > Now, there is a difference between how the ExceptionConverterImpl handles > StaleStateException and StaleObjectStateException because for the latter, > it tries to fetch the entity in question: > > final Object entity = sharedSessionContract.load( sose.getEntityName(), > identifier ); > > Because there is no proxy loaded in the current Session, the > DefaultLoadEntityListener will execute the createProxyIfNecessary method, > and because the entity was deleted, it will return null: > > EntityEntry entry = persistenceContext.getEntry( existing ); > Status status = entry.getStatus(); > if ( status == Status.DELETED || status == Status.GONE ) { > return null; > } > > However, getReference() throws an exception when there is no object being > found: > > getFactory().getEntityNotFoundDelegate().handleEntityNotFound( > entityPersister.getEntityName(), > id > ); > > So instead of a StaleObjectStateException, we get > an ObjectNotFoundException. > > One quick fix is to just catch that ObjectNotFoundException: > > Object entity; > try { > entity = sharedSessionContract.load( sose.getEntityName(), identifier > ); > } catch(ObjectNotFoundException e) { > entity = null; > } > > if ( entity instanceof Serializable ) { > //avoid some user errors regarding boundary crossing > pe = new OptimisticLockException( e.getMessage(), e, entity ); > } > else { > pe = new OptimisticLockException( e.getMessage(), e ); > } > > Or maybe there is some other fix that you might think of. > > Vlad > _______________________________________________ > hibernate-dev mailing list > hibernate-dev@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/hibernate-dev > _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev