use of java.io.Serializable in project hibernate-orm by hibernate.
the class TwoPhaseLoad method doInitializeEntity.
private static void doInitializeEntity(final Object entity, final EntityEntry entityEntry, final boolean readOnly, final SharedSessionContractImplementor session, final PreLoadEvent preLoadEvent) throws HibernateException {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityPersister persister = entityEntry.getPersister();
final Serializable id = entityEntry.getId();
final Object[] hydratedState = entityEntry.getLoadedState();
final boolean debugEnabled = LOG.isDebugEnabled();
if (debugEnabled) {
LOG.debugf("Resolving associations for %s", MessageHelper.infoString(persister, id, session.getFactory()));
}
final Type[] types = persister.getPropertyTypes();
for (int i = 0; i < hydratedState.length; i++) {
final Object value = hydratedState[i];
if (value == LazyPropertyInitializer.UNFETCHED_PROPERTY) {
// No resolution is necessary, unless the lazy property is a collection.
if (types[i].isCollectionType()) {
// IMPLEMENTATION NOTE: this is a lazy collection property on a bytecode-enhanced entity.
// HHH-10989: We need to resolve the collection so that a CollectionReference is added to StatefulPersistentContext.
// As mentioned above, hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY
// so do not assign the resolved, unitialized PersistentCollection back to hydratedState[i].
types[i].resolve(value, session, entity);
}
} else if (value != PropertyAccessStrategyBackRefImpl.UNKNOWN) {
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY
hydratedState[i] = types[i].resolve(value, session, entity);
}
}
//Must occur afterQuery resolving identifiers!
if (session.isEventSource()) {
preLoadEvent.setEntity(entity).setState(hydratedState).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(entity, hydratedState);
final SessionFactoryImplementor factory = session.getFactory();
if (persister.hasCache() && session.getCacheMode().isPutEnabled()) {
if (debugEnabled) {
LOG.debugf("Adding entity to second-level cache: %s", MessageHelper.infoString(persister, id, session.getFactory()));
}
final Object version = Versioning.getVersion(hydratedState, persister);
final CacheEntry entry = persister.buildCacheEntry(entity, hydratedState, version, session);
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
final Object cacheKey = cache.generateCacheKey(id, persister, factory, session.getTenantIdentifier());
// we need to be careful not to clobber the lock here in the cache so that it can be rolled back if need be
if (session.getPersistenceContext().wasInsertedDuringTransaction(persister, id)) {
cache.update(session, cacheKey, persister.getCacheEntryStructure().structure(entry), version, version);
} else {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
try {
eventListenerManager.cachePutStart();
final boolean put = cache.putFromLoad(session, cacheKey, persister.getCacheEntryStructure().structure(entry), session.getTimestamp(), version, useMinimalPuts(session, entityEntry));
if (put && factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().secondLevelCachePut(cache.getRegion().getName());
}
} finally {
eventListenerManager.cachePutEnd();
}
}
}
if (persister.hasNaturalIdentifier()) {
persistenceContext.getNaturalIdHelper().cacheNaturalIdCrossReferenceFromLoad(persister, id, persistenceContext.getNaturalIdHelper().extractNaturalIdValues(hydratedState, persister));
}
boolean isReallyReadOnly = readOnly;
if (!persister.isMutable()) {
isReallyReadOnly = true;
} else {
final Object proxy = persistenceContext.getProxy(entityEntry.getEntityKey());
if (proxy != null) {
// there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only
isReallyReadOnly = ((HibernateProxy) proxy).getHibernateLazyInitializer().isReadOnly();
}
}
if (isReallyReadOnly) {
//no need to take a snapshot - this is a
//performance optimization, but not really
//important, except for entities with huge
//mutable property values
persistenceContext.setEntryStatus(entityEntry, Status.READ_ONLY);
} else {
//take a snapshot
TypeHelper.deepCopy(hydratedState, persister.getPropertyTypes(), persister.getPropertyUpdateability(), //afterQuery setting values to object
hydratedState, session);
persistenceContext.setEntryStatus(entityEntry, Status.MANAGED);
}
persister.afterInitialize(entity, session);
if (debugEnabled) {
LOG.debugf("Done materializing entity %s", MessageHelper.infoString(persister, id, session.getFactory()));
}
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().loadEntity(persister.getEntityName());
}
}
use of java.io.Serializable in project hibernate-orm by hibernate.
the class AbstractSaveEventListener method performSaveOrReplicate.
/**
* 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
* afterQuery 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 inTxn = source.isTransactionInProgress();
boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
// Put a placeholder in entries, so we don't recurse back and try to save() the
// same object again. QUESTION: should this be done beforeQuery onSave() is called?
// likewise, should it be done beforeQuery 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;
}
use of java.io.Serializable in project hibernate-orm by hibernate.
the class AbstractSaveEventListener method saveWithGeneratedId.
/**
* Prepares the save call using a newly generated id.
*
* @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved
* @param anything Generally cascade-specific information.
* @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately afterQuery execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
*
* @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 saveWithGeneratedId(Object entity, String entityName, Object anything, EventSource source, boolean requiresImmediateIdAccess) {
if (entity instanceof SelfDirtinessTracker) {
((SelfDirtinessTracker) entity).$$_hibernate_clearDirtyAttributes();
}
EntityPersister persister = source.getEntityPersister(entityName, entity);
Serializable generatedId = persister.getIdentifierGenerator().generate(source, entity);
if (generatedId == null) {
throw new IdentifierGenerationException("null id generated for:" + entity.getClass());
} else if (generatedId == IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR) {
return source.getIdentifier(entity);
} else if (generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR) {
return performSave(entity, null, persister, true, anything, source, requiresImmediateIdAccess);
} else {
// TODO: define toString()s for generators
if (LOG.isDebugEnabled()) {
LOG.debugf("Generated identifier: %s, using strategy: %s", persister.getIdentifierType().toLoggableString(generatedId, source.getFactory()), persister.getIdentifierGenerator().getClass().getName());
}
return performSave(entity, generatedId, persister, false, anything, source, true);
}
}
use of java.io.Serializable in project hibernate-orm by hibernate.
the class DefaultDeleteEventListener method onDelete.
/**
* Handle the given delete event. This is the cascaded form.
*
* @param event The delete event.
* @param transientEntities The cache of entities already deleted
*
* @throws HibernateException
*/
public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException {
final EventSource source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContext();
Object entity = persistenceContext.unproxyAndReassociate(event.getObject());
EntityEntry entityEntry = persistenceContext.getEntry(entity);
final EntityPersister persister;
final Serializable id;
final Object version;
if (entityEntry == null) {
LOG.trace("Entity was not persistent in delete processing");
persister = source.getEntityPersister(event.getEntityName(), entity);
if (ForeignKeys.isTransient(persister.getEntityName(), entity, null, source)) {
deleteTransientEntity(source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities);
// EARLY EXIT!!!
return;
}
performDetachedEntityDeletionCheck(event);
id = persister.getIdentifier(entity, source);
if (id == null) {
throw new TransientObjectException("the detached instance passed to delete() had a null identifier");
}
final EntityKey key = source.generateEntityKey(id, persister);
persistenceContext.checkUniqueness(key, entity);
new OnUpdateVisitor(source, id, entity).process(entity, persister);
version = persister.getVersion(entity);
entityEntry = persistenceContext.addEntity(entity, (persister.isMutable() ? Status.MANAGED : Status.READ_ONLY), persister.getPropertyValues(entity), key, version, LockMode.NONE, true, persister, false);
} else {
LOG.trace("Deleting a persistent instance");
if (entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE) {
LOG.trace("Object was already deleted");
return;
}
persister = entityEntry.getPersister();
id = entityEntry.getId();
version = entityEntry.getVersion();
}
if (invokeDeleteLifecycle(source, entity, persister)) {
return;
}
deleteEntity(source, entity, entityEntry, event.isCascadeDeleteEnabled(), event.isOrphanRemovalBeforeUpdates(), persister, transientEntities);
if (source.getFactory().getSettings().isIdentifierRollbackEnabled()) {
persister.resetIdentifier(entity, id, version, source);
}
}
use of java.io.Serializable in project hibernate-orm by hibernate.
the class CollectionLoadContext method addCollectionToCache.
/**
* Add the collection to the second-level cache
*
* @param lce The entry representing the collection to add
* @param persister The persister
*/
private void addCollectionToCache(LoadingCollectionEntry lce, CollectionPersister persister) {
final SharedSessionContractImplementor session = getLoadContext().getPersistenceContext().getSession();
final SessionFactoryImplementor factory = session.getFactory();
final boolean debugEnabled = LOG.isDebugEnabled();
if (debugEnabled) {
LOG.debugf("Caching collection: %s", MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session));
}
if (!session.getLoadQueryInfluencers().getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters(session)) {
// some filters affecting the collection are enabled on the session, so do not do the put into the cache.
if (debugEnabled) {
LOG.debug("Refusing to add to cache due to enabled filters");
}
// EARLY EXIT!!!!!
return;
}
final Object version;
if (persister.isVersioned()) {
Object collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner(lce.getKey(), persister);
if (collectionOwner == null) {
// resolution against the PC anyway just to be safe since the lookup should not be costly.
if (lce.getCollection() != null) {
final Object linkedOwner = lce.getCollection().getOwner();
if (linkedOwner != null) {
final Serializable ownerKey = persister.getOwnerEntityPersister().getIdentifier(linkedOwner, session);
collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner(ownerKey, persister);
}
}
if (collectionOwner == null) {
throw new HibernateException("Unable to resolve owner of loading collection [" + MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session) + "] for second level caching");
}
}
version = getLoadContext().getPersistenceContext().getEntry(collectionOwner).getVersion();
} else {
version = null;
}
final CollectionCacheEntry entry = new CollectionCacheEntry(lce.getCollection(), persister);
final CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy();
final Object cacheKey = cache.generateCacheKey(lce.getKey(), persister, session.getFactory(), session.getTenantIdentifier());
boolean isPutFromLoad = true;
if (persister.getElementType().isAssociationType()) {
for (Serializable id : entry.getState()) {
EntityPersister entityPersister = ((QueryableCollection) persister).getElementPersister();
if (session.getPersistenceContext().wasInsertedDuringTransaction(entityPersister, id)) {
isPutFromLoad = false;
break;
}
}
}
// CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad
if (isPutFromLoad) {
try {
session.getEventListenerManager().cachePutStart();
final boolean put = cache.putFromLoad(session, cacheKey, persister.getCacheEntryStructure().structure(entry), session.getTimestamp(), version, factory.getSessionFactoryOptions().isMinimalPutsEnabled() && session.getCacheMode() != CacheMode.REFRESH);
if (put && factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().secondLevelCachePut(persister.getCacheAccessStrategy().getRegion().getName());
}
} finally {
session.getEventListenerManager().cachePutEnd();
}
}
}
Aggregations