When an update is performed on a lazy one-to-one association with optimistic locking set to {{OptimisticLockType.DIRTY}} previous state of that association is not loaded, leading to missing parameters required to perform an update statement.
With a model like:
{code:java}@Entity(name = "Person") @OptimisticLocking(type = OptimisticLockType.DIRTY) @DynamicUpdate public static class Person {
@Id Long id;
@Column String name;
// NOTE: issue is only reproducable with lazy fetching // and enabled bytecode enhancement @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) Address address; }
@Entity(name = "Address") @OptimisticLocking(type = OptimisticLockType.DIRTY) @DynamicUpdate public static class Address { @Id Long id;
@Column String street; }{code}
Then an operation that leads to an error:
{code:java}// get a person that has a lazy address Person person = entityManager.find( Person.class, 1L ); // set a new value to a lazy association: person.getAddress().setStreet( "new Street" );{code}
Results in:
{noformat}# Query executed: Hibernate: update Address set street=? where id=? and street=?
binding parameter (1:VARCHAR) <- [new Street] binding parameter (2:BIGINT) <- [10]
SQL Error: 90012, SQLState: 90012 Parameter "#3" is not set; SQL statement: update Address set street=? where id=? and street=? [90012-214]
# Error stack trace:
Caused by: org.hibernate.exception.DataException: could not execute statement [Parameter "#3" is not set; SQL statement: update Address set street=? where id=? and street=? [90012-214]] [update Address set street=? where id=? and street=?] at app//org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:53) at app//org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56) at app//org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108) at app//org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:278) at app//org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:108) at app//org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40) at app//org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:53) at app//org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.doDynamicUpdate(UpdateCoordinatorStandard.java:947) at app//org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.performUpdate(UpdateCoordinatorStandard.java:287) at app//org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.coordinateUpdate(UpdateCoordinatorStandard.java:217) at app//org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2731) at app//org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:166) at app//org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:633) at app//org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:502) at app//org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:363) at app//org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at app//org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) at app//org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1414) at app//org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:496) at app//org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2324) at app//org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1987) at app//org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439) at app//org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169) at app//org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267) at app//org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101){noformat}
Will submit a A reproducer : [https://github . com/hibernate/hibernate-orm/pull/6862|https://github.com/hibernate/hibernate-orm/pull/6862|smart-link] |
|