[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