下面列出了怎么用org.hibernate.type.TypeHelper的API类实例代码及写法,或者点击链接到github查看源代码。
protected void copyValues(
final EntityPersister persister,
final Object entity,
final Object target,
final SessionImplementor source,
final MergeContext copyCache) {
final Object[] copiedValues = TypeHelper.replace(
persister.getPropertyValues( entity ),
persister.getPropertyValues( target ),
persister.getPropertyTypes(),
source,
target,
copyCache
);
persister.setPropertyValues( target, copiedValues );
}
/**
* Locate the property-indices of all properties considered to be dirty.
*
* @param currentState The current state of the entity (the state to be checked).
* @param previousState The previous state of the entity (the state to be checked against).
* @param entity The entity for which we are checking state dirtiness.
* @param session The session in which the check is occurring.
*
* @return <tt>null</tt> or the indices of the dirty properties
*
* @throws HibernateException
*/
public int[] findDirty(Object[] currentState, Object[] previousState, Object entity, SharedSessionContractImplementor session)
throws HibernateException {
int[] props = TypeHelper.findDirty(
entityMetamodel.getProperties(),
currentState,
previousState,
propertyColumnUpdateable,
session
);
if ( props == null ) {
return null;
}
else {
logDirtyProperties( props );
return props;
}
}
/**
* Locate the property-indices of all properties considered to be dirty.
*
* @param old The old state of the entity.
* @param current The current state of the entity.
* @param entity The entity for which we are checking state modification.
* @param session The session in which the check is occurring.
*
* @return <tt>null</tt> or the indices of the modified properties
*
* @throws HibernateException
*/
public int[] findModified(Object[] old, Object[] current, Object entity, SharedSessionContractImplementor session)
throws HibernateException {
int[] props = TypeHelper.findModified(
entityMetamodel.getProperties(),
current,
old,
propertyColumnUpdateable,
getPropertyUpdateability(),
session
);
if ( props == null ) {
return null;
}
else {
logDirtyProperties( props );
return props;
}
}
/**
* Constructs a StandardCacheEntryImpl
*
* @param state The extracted state
* @param persister The entity persister
* @param version The current version (if versioned)
* @param session The originating session
* @param owner The owner
*
* @throws HibernateException Generally indicates a problem performing the dis-assembly.
*/
public StandardCacheEntryImpl(
final Object[] state,
final EntityPersister persister,
final Object version,
final SharedSessionContractImplementor session,
final Object owner) throws HibernateException {
// disassembled state gets put in a new array (we write to cache by value!)
this.disassembledState = TypeHelper.disassemble(
state,
persister.getPropertyTypes(),
persister.isLazyPropertiesCacheable() ? null : persister.getPropertyLaziness(),
session,
owner
);
this.subclass = persister.getEntityName();
this.version = version;
}
@SuppressWarnings("unchecked")
private List assembleCachedResult(
final QueryKey key,
final List cached,
boolean singleResult,
final Type[] returnTypes,
final SharedSessionContractImplementor session) throws HibernateException {
final List result = new ArrayList( cached.size() );
if ( singleResult ) {
for ( Object aCached : cached ) {
result.add( returnTypes[0].assemble( (Serializable) aCached, session, null ) );
}
}
else {
for ( int i = 0; i < cached.size(); i++ ) {
result.add(
TypeHelper.assemble( (Serializable[]) cached.get( i ), returnTypes, session, null )
);
if ( TRACING ) {
logCachedResultRowDetails( returnTypes, result.get( i ) );
}
}
}
return result;
}
protected void copyValues(
final EntityPersister persister,
final Object entity,
final Object target,
final SessionImplementor source,
final Map copyCache) {
final Object[] copiedValues = TypeHelper.replace(
persister.getPropertyValues( entity ),
persister.getPropertyValues( target ),
persister.getPropertyTypes(),
source,
target,
copyCache
);
persister.setPropertyValues( target, copiedValues );
}
private Object[] createDeletedState(EntityPersister persister, Object[] currentState, EventSource session) {
Type[] propTypes = persister.getPropertyTypes();
final Object[] deletedState = new Object[propTypes.length];
// TypeFactory.deepCopy( currentState, propTypes, persister.getPropertyUpdateability(), deletedState, session );
boolean[] copyability = new boolean[propTypes.length];
java.util.Arrays.fill( copyability, true );
TypeHelper.deepCopy( currentState, propTypes, copyability, deletedState, session );
return deletedState;
}
protected void copyValues(
final EntityPersister persister,
final Object entity,
final Object target,
final SessionImplementor source,
final MergeContext copyCache,
final ForeignKeyDirection foreignKeyDirection) {
final Object[] copiedValues;
if ( foreignKeyDirection == ForeignKeyDirection.TO_PARENT ) {
// this is the second pass through on a merge op, so here we limit the
// replacement to associations types (value types were already replaced
// during the first pass)
copiedValues = TypeHelper.replaceAssociations(
persister.getPropertyValues( entity ),
persister.getPropertyValues( target ),
persister.getPropertyTypes(),
source,
target,
copyCache,
foreignKeyDirection
);
}
else {
copiedValues = TypeHelper.replace(
persister.getPropertyValues( entity ),
persister.getPropertyValues( target ),
persister.getPropertyTypes(),
source,
target,
copyCache,
foreignKeyDirection
);
}
persister.setPropertyValues( target, copiedValues );
}
/**
* Assemble the previously disassembled state represented by this entry into the given entity instance.
*
* Additionally manages the PreLoadEvent callbacks.
*
* @param instance The entity instance
* @param id The entity identifier
* @param persister The entity persister
* @param interceptor (currently unused)
* @param session The session
*
* @return The assembled state
*
* @throws HibernateException Indicates a problem performing assembly or calling the PreLoadEventListeners.
*
* @see org.hibernate.type.Type#assemble
* @see org.hibernate.type.Type#disassemble
*/
public Object[] assemble(
final Object instance,
final Serializable id,
final EntityPersister persister,
final Interceptor interceptor,
final EventSource session) throws HibernateException {
if ( !persister.getEntityName().equals( subclass ) ) {
throw new AssertionFailure( "Tried to assemble a different subclass instance" );
}
//assembled state gets put in a new array (we read from cache by value!)
final Object[] state = TypeHelper.assemble(
disassembledState,
persister.getPropertyTypes(),
session, instance
);
//persister.setIdentifier(instance, id); //before calling interceptor, for consistency with normal load
//TODO: reuse the PreLoadEvent
final PreLoadEvent preLoadEvent = new PreLoadEvent( session )
.setEntity( instance )
.setState( state )
.setId( id )
.setPersister( persister );
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD );
for ( PreLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPreLoad( preLoadEvent );
}
persister.setPropertyValues( instance, state );
return state;
}
private Object[] createDeletedState(EntityPersister persister, Object[] currentState, EventSource session) {
Type[] propTypes = persister.getPropertyTypes();
final Object[] deletedState = new Object[propTypes.length];
// TypeFactory.deepCopy( currentState, propTypes, persister.getPropertyUpdateability(), deletedState, session );
boolean[] copyability = new boolean[propTypes.length];
java.util.Arrays.fill( copyability, true );
TypeHelper.deepCopy( currentState, propTypes, copyability, deletedState, session );
return deletedState;
}
protected void copyValues(
final EntityPersister persister,
final Object entity,
final Object target,
final SessionImplementor source,
final Map copyCache,
final ForeignKeyDirection foreignKeyDirection) {
final Object[] copiedValues;
if ( foreignKeyDirection == ForeignKeyDirection.TO_PARENT ) {
// this is the second pass through on a merge op, so here we limit the
// replacement to associations types (value types were already replaced
// during the first pass)
copiedValues = TypeHelper.replaceAssociations(
persister.getPropertyValues( entity ),
persister.getPropertyValues( target ),
persister.getPropertyTypes(),
source,
target,
copyCache,
foreignKeyDirection
);
}
else {
copiedValues = TypeHelper.replace(
persister.getPropertyValues( entity ),
persister.getPropertyValues( target ),
persister.getPropertyTypes(),
source,
target,
copyCache,
foreignKeyDirection
);
}
persister.setPropertyValues( target, copiedValues );
}
@Override
@SuppressWarnings({ "unchecked" })
public boolean put(
final QueryKey key,
final List results,
final Type[] returnTypes,
final SharedSessionContractImplementor session) throws HibernateException {
if ( DEBUGGING ) {
LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), session.getTransactionStartTimestamp() );
}
final List resultsCopy = CollectionHelper.arrayList( results.size() );
final boolean isSingleResult = returnTypes.length == 1;
for ( Object aResult : results ) {
final Serializable resultRowForCache;
if ( isSingleResult ) {
resultRowForCache = returnTypes[0].disassemble( aResult, session, null );
}
else {
resultRowForCache = TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
}
resultsCopy.add( resultRowForCache );
if ( TRACING ) {
logCachedResultRowDetails( returnTypes, aResult );
}
}
if ( TRACING ) {
logCachedResultDetails( key, null, returnTypes, resultsCopy );
}
final CacheItem cacheItem = new CacheItem(
session.getTransactionStartTimestamp(),
resultsCopy
);
try {
session.getEventListenerManager().cachePutStart();
cacheRegion.putIntoCache( key, cacheItem, session );
}
finally {
session.getEventListenerManager().cachePutEnd();
}
return true;
}
@Override
@SuppressWarnings({ "unchecked" })
public List get(
final QueryKey key,
final String[] spaces,
final Type[] returnTypes,
final SharedSessionContractImplementor session) {
if ( DEBUGGING ) {
LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() );
}
final CacheItem cacheItem = getCachedData( key, session );
if ( cacheItem == null ) {
if ( DEBUGGING ) {
LOG.debug( "Query results were not found in cache" );
}
return null;
}
if ( !timestampsCache.isUpToDate( spaces, cacheItem.timestamp, session ) ) {
if ( DEBUGGING ) {
LOG.debug( "Cached query results were not up-to-date" );
}
return null;
}
if ( DEBUGGING ) {
LOG.debug( "Returning cached query results" );
}
final boolean singleResult = returnTypes.length == 1;
for ( int i = 0; i < cacheItem.results.size(); i++ ) {
if ( singleResult ) {
returnTypes[0].beforeAssemble( (Serializable) cacheItem.results.get( i ), session );
}
else {
TypeHelper.beforeAssemble( (Serializable[]) cacheItem.results.get( i ), returnTypes, session );
}
}
return assembleCachedResult( key, cacheItem.results, singleResult, returnTypes, session );
}
private Object convertCacheEntryToEntity(
CacheEntry entry,
Serializable entityId,
EntityPersister persister,
LoadEvent event,
EntityKey entityKey) {
final EventSource session = event.getSession();
final SessionFactoryImplementor factory = session.getFactory();
final EntityPersister subclassPersister;
if ( traceEnabled ) {
LOG.tracef(
"Converting second-level cache entry [%s] into entity : %s",
entry,
MessageHelper.infoString( persister, entityId, factory )
);
}
final Object entity;
subclassPersister = factory.getEntityPersister( entry.getSubclass() );
final Object optionalObject = event.getInstanceToLoad();
entity = optionalObject == null
? session.instantiate( subclassPersister, entityId )
: optionalObject;
// make it circular-reference safe
TwoPhaseLoad.addUninitializedCachedEntity(
entityKey,
entity,
subclassPersister,
LockMode.NONE,
entry.getVersion(),
session
);
final PersistenceContext persistenceContext = session.getPersistenceContext();
final Object[] values;
final Object version;
final boolean isReadOnly;
final Type[] types = subclassPersister.getPropertyTypes();
// initializes the entity by (desired) side-effect
values = ( (StandardCacheEntryImpl) entry ).assemble(
entity, entityId, subclassPersister, session.getInterceptor(), session
);
if ( ( (StandardCacheEntryImpl) entry ).isDeepCopyNeeded() ) {
TypeHelper.deepCopy(
values,
types,
subclassPersister.getPropertyUpdateability(),
values,
session
);
}
version = Versioning.getVersion( values, subclassPersister );
LOG.tracef( "Cached Version : %s", version );
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
// there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only
isReadOnly = ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isReadOnly();
}
else {
isReadOnly = session.isDefaultReadOnly();
}
persistenceContext.addEntry(
entity,
( isReadOnly ? Status.READ_ONLY : Status.MANAGED ),
values,
null,
entityId,
version,
LockMode.NONE,
true,
subclassPersister,
false
);
subclassPersister.afterInitialize( entity, session );
persistenceContext.initializeNonLazyCollections();
//PostLoad is needed for EJB3
PostLoadEvent postLoadEvent = event.getPostLoadEvent()
.setEntity( entity )
.setId( entityId )
.setPersister( persister );
for ( PostLoadEventListener listener : postLoadEventListeners( session ) ) {
listener.onPostLoad( postLoadEvent );
}
return entity;
}
/**
* Associates a given entity (either transient or associated with another session) to
* the given session.
*
* @param event The event triggering the re-association
* @param object The entity to be associated
* @param id The id of the entity.
* @param persister The entity's persister instance.
*
* @return An EntityEntry representing the entity within this session.
*/
protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister) {
if ( log.isTraceEnabled() ) {
log.tracev(
"Reassociating transient instance: {0}",
MessageHelper.infoString( persister, id, event.getSession().getFactory() )
);
}
final EventSource source = event.getSession();
final EntityKey key = source.generateEntityKey( id, persister );
source.getPersistenceContext().checkUniqueness( key, object );
//get a snapshot
Object[] values = persister.getPropertyValues( object );
TypeHelper.deepCopy(
values,
persister.getPropertyTypes(),
persister.getPropertyUpdateability(),
values,
source
);
Object version = Versioning.getVersion( values, persister );
EntityEntry newEntry = source.getPersistenceContext().addEntity(
object,
( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
values,
key,
version,
LockMode.NONE,
true,
persister,
false
);
new OnLockVisitor( source, id, object ).process( object, persister );
persister.afterReassociate( object, source );
return newEntry;
}
/**
* Performs all the actual work needed to save an entity (well to get the save moved to
* the execution queue).
*
* @param entity The entity to be saved
* @param key The id to be used for saving the entity (or null, in the case of identity columns)
* @param persister The entity's persister instance.
* @param useIdentityColumn Should an identity column be used for id generation?
* @param anything Generally cascade-specific information.
* @param source The session which is the source of the current event.
* @param requiresImmediateIdAccess Is access to the identifier required immediately
* after the completion of the save? persist(), for example, does not require this...
*
* @return The id used to save the entity; may be null depending on the
* type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable performSaveOrReplicate(
Object entity,
EntityKey key,
EntityPersister persister,
boolean useIdentityColumn,
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
Serializable id = key == null ? null : key.getIdentifier();
boolean shouldDelayIdentityInserts = shouldDelayIdentityInserts( requiresImmediateIdAccess, source );
// Put a placeholder in entries, so we don't recurse back and try to save() the
// same object again. QUESTION: should this be done before onSave() is called?
// likewise, should it be done before onUpdate()?
EntityEntry original = source.getPersistenceContext().addEntry(
entity,
Status.SAVING,
null,
null,
id,
null,
LockMode.WRITE,
useIdentityColumn,
persister,
false
);
cascadeBeforeSave( source, persister, entity, anything );
Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( anything ), source );
Type[] types = persister.getPropertyTypes();
boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );
if ( persister.hasCollections() ) {
substitute = substitute || visitCollectionsBeforeSave( entity, id, values, types, source );
}
if ( substitute ) {
persister.setPropertyValues( entity, values );
}
TypeHelper.deepCopy(
values,
types,
persister.getPropertyUpdateability(),
values,
source
);
AbstractEntityInsertAction insert = addInsertAction(
values, id, entity, persister, useIdentityColumn, source, shouldDelayIdentityInserts
);
// postpone initializing id in case the insert has non-nullable transient dependencies
// that are not resolved until cascadeAfterSave() is executed
cascadeAfterSave( source, persister, entity, anything );
if ( useIdentityColumn && insert.isEarlyInsert() ) {
if ( !EntityIdentityInsertAction.class.isInstance( insert ) ) {
throw new IllegalStateException(
"Insert should be using an identity column, but action is of unexpected type: " +
insert.getClass().getName()
);
}
id = ((EntityIdentityInsertAction) insert).getGeneratedId();
insert.handleNaturalIdPostSaveNotifications( id );
}
EntityEntry newEntry = source.getPersistenceContext().getEntry( entity );
if ( newEntry != original ) {
EntityEntryExtraState extraState = newEntry.getExtraState( EntityEntryExtraState.class );
if ( extraState == null ) {
newEntry.addExtraState( original.getExtraState( EntityEntryExtraState.class ) );
}
}
return id;
}