@Override
	public void update(
			final Serializable id,
			final Object[] fields,
			final int[] dirtyFields,
			final boolean hasDirtyCollection,
			final Object[] oldFields,
			final Object oldVersion,
			final Object object,
			final Object rowId,
			final SharedSessionContractImplementor session) throws HibernateException {

		//note: dirtyFields==null means we had no snapshot, and we couldn't get one using select-before-update
		//	  oldFields==null just means we had no snapshot to begin with (we might have used select-before-update to get the dirtyFields)

		//TODO support "multi table" entities
		final boolean[] tableUpdateNeeded = getTableUpdateNeeded( dirtyFields, hasDirtyCollection );
		final int span = getTableSpan();

		final boolean[] propsToUpdate;
		EntityEntry entry = session.getPersistenceContext().getEntry( object );

		// Ensure that an immutable or non-modifiable entity is not being updated unless it is
		// in the process of being deleted.
		if ( entry == null && ! isMutable() ) {
			throw new IllegalStateException( "Updating immutable entity that is not in session yet!" );
		}
		//we always use a dynamicUpdate model for Infinispan
		if ( (
				//getEntityMetamodel().isDynamicUpdate() &&
				dirtyFields != null ) ) {

			propsToUpdate = getPropertiesToUpdate( dirtyFields, hasDirtyCollection );
			// don't need to check laziness (dirty checking algorithm handles that)
		}
		else if ( ! isModifiableEntity( entry ) ) {
			//TODO does that apply to OGM?
			// We need to generate UPDATE SQL when a non-modifiable entity (e.g., read-only or immutable)
			// needs:
			// - to have references to transient entities set to null before being deleted
			// - to have version incremented do to a "dirty" association
			// If dirtyFields == null, then that means that there are no dirty properties to
			// to be updated; an empty array for the dirty fields needs to be passed to
			// getPropertiesToUpdate() instead of null.
			propsToUpdate = getPropertiesToUpdate(
					( dirtyFields == null ? ArrayHelper.EMPTY_INT_ARRAY : dirtyFields ),
					hasDirtyCollection
			);
			// don't need to check laziness (dirty checking algorithm handles that)
		}
		else {
			// For the case of dynamic-update="false", or no snapshot, we update all properties
			//TODO handle lazy
			propsToUpdate = getPropertyUpdateability( object );
		}

		final SessionFactoryImplementor factory = getFactory();
		if ( log.isTraceEnabled() ) {
			log.trace( "Updating entity: " + MessageHelper.infoString( this, id, factory ) );
			if ( isVersioned() ) {
				log.trace( "Existing version: " + oldVersion + " -> New version: " + fields[getVersionProperty()] );
			}
		}


		for ( int j = 0; j < span; j++ ) {
			// Now update only the tables with dirty properties (and the table with the version number)
			if ( tableUpdateNeeded[j] ) {
				final EntityKey key = EntityKeyBuilder.fromPersister( this, id, session );

				final boolean useVersion = j == 0 && isVersioned();

				if ( usesNonAtomicOptimisticLocking ) {
					final Tuple tupleInDatastore = getFreshTuple( key, session );
					final EntityMetamodel entityMetamodel = getEntityMetamodel();

					// Write any appropriate versioning conditional parameters
					if ( useVersion && entityMetamodel.getOptimisticLockStyle() == OptimisticLockStyle.VERSION ) {
						if ( checkVersion( propsToUpdate ) ) {
							checkVersionAndRaiseSOSE( id, oldVersion, session, tupleInDatastore );
						}
					}
					else if ( isAllOrDirtyOptLocking() && oldFields != null ) {
						boolean[] versionability = getPropertyVersionability(); //TODO: is this really necessary????
						boolean[] includeOldField = entityMetamodel.getOptimisticLockStyle() == OptimisticLockStyle.ALL
								? getPropertyUpdateability()
										: propsToUpdate;

						//TODO do a diff on the properties value from resultset and the dirty value
						GridType[] types = gridPropertyTypes;

						for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
							boolean include = includeOldField[i] &&
									isPropertyOfTable( i, j ) &&
									versionability[i]; //TODO: is this really necessary????
							if ( include ) {
								final GridType type = types[i];
								//FIXME what do do with settable?
								boolean[] settable = type.toColumnNullness( oldFields[i], factory );
								final Object snapshotValue = type.nullSafeGet(
										tupleInDatastore, getPropertyColumnNames( i ), session, object
										);

								if ( !type.isEqual( oldFields[i], snapshotValue, factory ) ) {
									raiseStaleObjectStateException( id );
								}
							}
						}
					}
				}

				TuplePointer tuplePointer = getSharedTuplePointer( key, object, session );
				Tuple resultset = tuplePointer.getTuple();
				resultset = createNewResultSetIfNull( key, resultset, id, session );
				resultset.setSnapshotType( SnapshotType.UPDATE );
				saveSharedTuple( object, resultset, session );

				if ( mightManageInverseAssociations ) {
					removeFromInverseAssociations( resultset, j, id, session );
				}
				dehydrate( resultset, fields, propsToUpdate, j, id, session );

				// TODO OGM-616 Also use this facet for "all columns" optimistic locking strategy
				if ( isVersioned() && optimisticLockingAwareGridDialect != null ) {
					Tuple oldVersionTuple = new Tuple();
					oldVersionTuple.put( getVersionColumnName(), oldVersion );

					boolean success = optimisticLockingAwareGridDialect.updateTupleWithOptimisticLock( key, oldVersionTuple, resultset, getTupleContext( session ) );

					// If there is an error handler registered, pass the applied/failed operation to it as needed
					if ( success ) {
						if ( invocationCollectingGridDialect != null ) {
							invocationCollectingGridDialect.onUpdateTupleWithOptimisticLockSuccess( key, oldVersionTuple, resultset );
						}
					}
					else {
						if ( invocationCollectingGridDialect != null ) {
							try {
								raiseStaleObjectStateException( id );
							}
							catch (Exception e) {
								invocationCollectingGridDialect.onUpdateTupleWithOptimisticLockFailure( key, oldVersionTuple, resultset, e );
							}
						}
						else {
							raiseStaleObjectStateException( id );
						}
					}
				}
				else {
					insertOrUpdateTuple( key, tuplePointer, hasUpdateGeneratedProperties(), session );
				}

				if ( mightManageInverseAssociations ) {
					addToInverseAssociations( resultset, j, id, session );
				}
			}
		}
	}
@ Override public void update ( final Serializable id , final Object [ ] fields , final int [ ] dirtyFields , final boolean hasDirtyCollection , final Object [ ] oldFields , final Object oldVersion , final Object object , final Object rowId , final SharedSessionContractImplementor session ) throws HibernateException { final boolean [ ] tableUpdateNeeded = getTableUpdateNeeded ( dirtyFields , hasDirtyCollection ) ; final int span = getTableSpan ( ) ; final boolean [ ] propsToUpdate ; EntityEntry entry = session . getPersistenceContext ( ) . getEntry ( object ) ; if ( entry == null && ! isMutable ( ) ) { throw new IllegalStateException ( "Updating immutable entity that is not in session yet!" ) ; } if ( ( dirtyFields != null ) ) { propsToUpdate = getPropertiesToUpdate ( dirtyFields , hasDirtyCollection ) ; } else if ( ! isModifiableEntity ( entry ) ) { propsToUpdate = getPropertiesToUpdate ( ( dirtyFields == null ? ArrayHelper . EMPTY_INT_ARRAY : dirtyFields ) , hasDirtyCollection ) ; } else { propsToUpdate = getPropertyUpdateability ( object ) ; } final SessionFactoryImplementor factory = getFactory ( ) ; if ( log . isTraceEnabled ( ) ) { log . trace ( "Updating entity: " + MessageHelper . infoString ( this , id , factory ) ) ; if ( isVersioned ( ) ) { log . trace ( "Existing version: " + oldVersion + " -> New version: " + fields [ getVersionProperty ( ) ] ) ; } } for ( int j = 0 ; j < span ; j ++ ) { if ( tableUpdateNeeded [ j ] ) { final EntityKey key = EntityKeyBuilder . fromPersister ( this , id , session ) ; final boolean useVersion = j == 0 && isVersioned ( ) ; if ( usesNonAtomicOptimisticLocking ) { final Tuple tupleInDatastore = getFreshTuple ( key , session ) ; final EntityMetamodel entityMetamodel = getEntityMetamodel ( ) ; if ( useVersion && entityMetamodel . getOptimisticLockStyle ( ) == OptimisticLockStyle . VERSION ) { if ( checkVersion ( propsToUpdate ) ) { checkVersionAndRaiseSOSE ( id , oldVersion , session , tupleInDatastore ) ; } } else if ( isAllOrDirtyOptLocking ( ) && oldFields != null ) { boolean [ ] versionability = getPropertyVersionability ( ) ; boolean [ ] includeOldField = entityMetamodel . getOptimisticLockStyle ( ) == OptimisticLockStyle . ALL ? getPropertyUpdateability ( ) : propsToUpdate ; GridType [ ] types = gridPropertyTypes ; for ( int i = 0 ; i < entityMetamodel . getPropertySpan ( ) ; i ++ ) { boolean include = includeOldField [ i ] && isPropertyOfTable ( i , j ) && versionability [ i ] ; if ( include ) { final GridType type = types [ i ] ; boolean [ ] settable = type . toColumnNullness ( oldFields [ i ] , factory ) ; final Object snapshotValue = type . nullSafeGet ( tupleInDatastore , getPropertyColumnNames ( i ) , session , object ) ; if ( ! type . isEqual ( oldFields [ i ] , snapshotValue , factory ) ) { raiseStaleObjectStateException ( id ) ; } } } } } TuplePointer tuplePointer = getSharedTuplePointer ( key , object , session ) ; Tuple resultset = tuplePointer . getTuple ( ) ; resultset = createNewResultSetIfNull ( key , resultset , id , session ) ; resultset . setSnapshotType ( SnapshotType . UPDATE ) ; saveSharedTuple ( object , resultset , session ) ; if ( mightManageInverseAssociations ) { removeFromInverseAssociations ( resultset , j , id , session ) ; } dehydrate ( resultset , fields , propsToUpdate , j , id , session ) ; if ( isVersioned ( ) && optimisticLockingAwareGridDialect != null ) { Tuple oldVersionTuple = new Tuple ( ) ; oldVersionTuple . put ( getVersionColumnName ( ) , oldVersion ) ; boolean success = optimisticLockingAwareGridDialect . updateTupleWithOptimisticLock ( key , oldVersionTuple , resultset , getTupleContext ( session ) ) ; if ( success ) { if ( invocationCollectingGridDialect != null ) { invocationCollectingGridDialect . onUpdateTupleWithOptimisticLockSuccess ( key , oldVersionTuple , resultset ) ; } } else { if ( invocationCollectingGridDialect != null ) { try { raiseStaleObjectStateException ( id ) ; } catch ( Exception e ) { invocationCollectingGridDialect . onUpdateTupleWithOptimisticLockFailure ( key , oldVersionTuple , resultset , e ) ; } } else { raiseStaleObjectStateException ( id ) ; } } } else { insertOrUpdateTuple ( key , tuplePointer , hasUpdateGeneratedProperties ( ) , session ) ; } if ( mightManageInverseAssociations ) { addToInverseAssociations ( resultset , j , id , session ) ; } } } }
Update an object