/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.engine.internal;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.VersionType;
import org.jboss.logging.Logger;
Utilities for dealing with optimistic locking values.
Author: Gavin King
/**
* Utilities for dealing with optimistic locking values.
*
* @author Gavin King
*/
public final class Versioning {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
Versioning.class.getName()
);
Private constructor disallowing instantiation.
/**
* Private constructor disallowing instantiation.
*/
private Versioning() {
}
Create an initial optimistic locking value according the VersionType
contract for the version property. Params: - versionType – The version type.
- session – The originating session
Returns: The initial optimistic locking value
/**
* Create an initial optimistic locking value according the {@link VersionType}
* contract for the version property.
*
* @param versionType The version type.
* @param session The originating session
* @return The initial optimistic locking value
*/
private static Object seed(VersionType versionType, SharedSessionContractImplementor session) {
final Object seed = versionType.seed( session );
LOG.tracef( "Seeding: %s", seed );
return seed;
}
Create an initial optimistic locking value according the VersionType
contract for the version property if required and inject it into
the snapshot state.
Params: - fields – The current snapshot state
- versionProperty – The index of the version property
- versionType – The version type
- session – The originating session
Returns: True if we injected a new version value into the fields array; false
otherwise.
/**
* Create an initial optimistic locking value according the {@link VersionType}
* contract for the version property <b>if required</b> and inject it into
* the snapshot state.
*
* @param fields The current snapshot state
* @param versionProperty The index of the version property
* @param versionType The version type
* @param session The originating session
* @return True if we injected a new version value into the fields array; false
* otherwise.
*/
public static boolean seedVersion(
Object[] fields,
int versionProperty,
VersionType versionType,
SharedSessionContractImplementor session) {
final Object initialVersion = fields[versionProperty];
if (
initialVersion==null ||
// This next bit is to allow for both unsaved-value="negative"
// and for "older" behavior where version number did not get
// seeded if it was already set in the object
// TODO: shift it into unsaved-value strategy
( (initialVersion instanceof Number) && ( (Number) initialVersion ).longValue()<0 )
) {
fields[versionProperty] = seed( versionType, session );
return true;
}
LOG.tracev( "Using initial version: {0}", initialVersion );
return false;
}
Generate the next increment in the optimistic locking value according the VersionType
contract for the version property. Params: - version – The current version
- versionType – The version type
- session – The originating session
Returns: The incremented optimistic locking value.
/**
* Generate the next increment in the optimistic locking value according
* the {@link VersionType} contract for the version property.
*
* @param version The current version
* @param versionType The version type
* @param session The originating session
* @return The incremented optimistic locking value.
*/
@SuppressWarnings("unchecked")
public static Object increment(Object version, VersionType versionType, SharedSessionContractImplementor session) {
final Object next = versionType.next( version, session );
if ( LOG.isTraceEnabled() ) {
LOG.tracef(
"Incrementing: %s to %s",
versionType.toLoggableString( version, session.getFactory() ),
versionType.toLoggableString( next, session.getFactory() )
);
}
return next;
}
Inject the optimistic locking value into the entity state snapshot.
Params: - fields – The state snapshot
- version – The optimistic locking value
- persister – The entity persister
/**
* Inject the optimistic locking value into the entity state snapshot.
*
* @param fields The state snapshot
* @param version The optimistic locking value
* @param persister The entity persister
*/
public static void setVersion(Object[] fields, Object version, EntityPersister persister) {
if ( !persister.isVersioned() ) {
return;
}
fields[ persister.getVersionProperty() ] = version;
}
Extract the optimistic locking value out of the entity state snapshot.
Params: - fields – The state snapshot
- persister – The entity persister
Returns: The extracted optimistic locking value
/**
* Extract the optimistic locking value out of the entity state snapshot.
*
* @param fields The state snapshot
* @param persister The entity persister
* @return The extracted optimistic locking value
*/
public static Object getVersion(Object[] fields, EntityPersister persister) {
if ( !persister.isVersioned() ) {
return null;
}
return fields[ persister.getVersionProperty() ];
}
Do we need to increment the version number, given the dirty properties?
Params: - dirtyProperties – The array of property indexes which were deemed dirty
- hasDirtyCollections – Were any collections found to be dirty (structurally changed)
- propertyVersionability – An array indicating versionability of each property.
Returns: True if a version increment is required; false otherwise.
/**
* Do we need to increment the version number, given the dirty properties?
*
* @param dirtyProperties The array of property indexes which were deemed dirty
* @param hasDirtyCollections Were any collections found to be dirty (structurally changed)
* @param propertyVersionability An array indicating versionability of each property.
* @return True if a version increment is required; false otherwise.
*/
public static boolean isVersionIncrementRequired(
final int[] dirtyProperties,
final boolean hasDirtyCollections,
final boolean[] propertyVersionability) {
if ( hasDirtyCollections ) {
return true;
}
for ( int dirtyProperty : dirtyProperties ) {
if ( propertyVersionability[dirtyProperty] ) {
return true;
}
}
return false;
}
}