[hibernate-dev] Possible regression on master

andrea boriero andrea at hibernate.org
Tue May 17 08:54:13 EDT 2016


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.vlad at 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 at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>


More information about the hibernate-dev mailing list