use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class DefaultLoadEventListener method createProxyIfNecessary.
/**
* If there is already a corresponding proxy associated with the
* persistence context, return it; otherwise create a proxy, associate it
* with the persistence context, and return the just-created proxy.
*
* @param event The initiating load request event
* @param persister The persister corresponding to the entity to be loaded
* @param keyToLoad The key of the entity to be loaded
* @param options The defined load options
* @param persistenceContext The originating session
*
* @return The created/existing proxy
*/
private Object createProxyIfNecessary(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options, final PersistenceContext persistenceContext) {
Object existing = persistenceContext.getEntity(keyToLoad);
if (existing != null) {
// return existing object or initialized proxy (unless deleted)
if (traceEnabled) {
LOG.trace("Entity found in session cache");
}
if (options.isCheckDeleted()) {
EntityEntry entry = persistenceContext.getEntry(existing);
Status status = entry.getStatus();
if (status == Status.DELETED || status == Status.GONE) {
return null;
}
}
return existing;
}
if (traceEnabled) {
LOG.trace("Creating new proxy for entity");
}
// return new uninitialized proxy
Object proxy = persister.createProxy(event.getEntityId(), event.getSession());
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad);
persistenceContext.addProxy(keyToLoad, proxy);
return proxy;
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class DefaultSaveOrUpdateEventListener method entityIsPersistent.
protected Serializable entityIsPersistent(SaveOrUpdateEvent event) throws HibernateException {
final boolean traceEnabled = LOG.isTraceEnabled();
if (traceEnabled) {
LOG.trace("Ignoring persistent instance");
}
EntityEntry entityEntry = event.getEntry();
if (entityEntry == null) {
throw new AssertionFailure("entity was transient or detached");
} else {
if (entityEntry.getStatus() == Status.DELETED) {
throw new AssertionFailure("entity was deleted");
}
final SessionFactoryImplementor factory = event.getSession().getFactory();
Serializable requestedId = event.getRequestedId();
Serializable savedId;
if (requestedId == null) {
savedId = entityEntry.getId();
} else {
final boolean isEqual = !entityEntry.getPersister().getIdentifierType().isEqual(requestedId, entityEntry.getId(), factory);
if (isEqual) {
throw new PersistentObjectException("object passed to save() was already persistent: " + MessageHelper.infoString(entityEntry.getPersister(), requestedId, factory));
}
savedId = requestedId;
}
if (traceEnabled) {
LOG.tracev("Object already associated with session: {0}", MessageHelper.infoString(entityEntry.getPersister(), savedId, factory));
}
return savedId;
}
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class Loader method initializeEntitiesAndCollections.
private void initializeEntitiesAndCollections(final List hydratedObjects, final Object resultSetId, final SharedSessionContractImplementor session, final boolean readOnly, List<AfterLoadAction> afterLoadActions) throws HibernateException {
final CollectionPersister[] collectionPersisters = getCollectionPersisters();
if (collectionPersisters != null) {
for (CollectionPersister collectionPersister : collectionPersisters) {
if (collectionPersister.isArray()) {
//for arrays, we should end the collection load beforeQuery resolving
//the entities, since the actual array instances are not instantiated
//during loading
//TODO: or we could do this polymorphically, and have two
// different operations implemented differently for arrays
endCollectionLoad(resultSetId, session, collectionPersister);
}
}
}
//important: reuse the same event instances for performance!
final PreLoadEvent pre;
final PostLoadEvent post;
if (session.isEventSource()) {
pre = new PreLoadEvent((EventSource) session);
post = new PostLoadEvent((EventSource) session);
} else {
pre = null;
post = null;
}
if (hydratedObjects != null) {
int hydratedObjectsSize = hydratedObjects.size();
LOG.tracev("Total objects hydrated: {0}", hydratedObjectsSize);
for (Object hydratedObject : hydratedObjects) {
TwoPhaseLoad.initializeEntity(hydratedObject, readOnly, session, pre);
}
}
if (collectionPersisters != null) {
for (CollectionPersister collectionPersister : collectionPersisters) {
if (!collectionPersister.isArray()) {
//for sets, we should end the collection load afterQuery resolving
//the entities, since we might call hashCode() on the elements
//TODO: or we could do this polymorphically, and have two
// different operations implemented differently for arrays
endCollectionLoad(resultSetId, session, collectionPersister);
}
}
}
// persistence context.
if (hydratedObjects != null) {
for (Object hydratedObject : hydratedObjects) {
TwoPhaseLoad.postLoad(hydratedObject, session, post);
if (afterLoadActions != null) {
for (AfterLoadAction afterLoadAction : afterLoadActions) {
final EntityEntry entityEntry = session.getPersistenceContext().getEntry(hydratedObject);
if (entityEntry == null) {
// big problem
throw new HibernateException("Could not locate EntityEntry immediately afterQuery two-phase load");
}
afterLoadAction.afterLoad(session, hydratedObject, (Loadable) entityEntry.getPersister());
}
}
}
}
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class EntityUpdateAction method execute.
@Override
public void execute() throws HibernateException {
final Serializable id = getId();
final EntityPersister persister = getPersister();
final SharedSessionContractImplementor session = getSession();
final Object instance = getInstance();
final boolean veto = preUpdate();
final SessionFactoryImplementor factory = session.getFactory();
Object previousVersion = this.previousVersion;
if (persister.isVersionPropertyGenerated()) {
// we need to grab the version value from the entity, otherwise
// we have issues with generated-version entities that may have
// multiple actions queued during the same flush
previousVersion = persister.getVersion(instance);
}
final Object ck;
if (persister.hasCache()) {
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
ck = cache.generateCacheKey(id, persister, factory, session.getTenantIdentifier());
lock = cache.lockItem(session, ck, previousVersion);
} else {
ck = null;
}
if (!veto) {
persister.update(id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, rowId, session);
}
final EntityEntry entry = session.getPersistenceContext().getEntry(instance);
if (entry == null) {
throw new AssertionFailure("possible nonthreadsafe access to session");
}
if (entry.getStatus() == Status.MANAGED || persister.isVersionPropertyGenerated()) {
// get the updated snapshot of the entity state by cloning current state;
// it is safe to copy in place, since by this time no-one else (should have)
// has a reference to the array
TypeHelper.deepCopy(state, persister.getPropertyTypes(), persister.getPropertyCheckability(), state, session);
if (persister.hasUpdateGeneratedProperties()) {
// this entity defines proeprty generation, so process those generated
// values...
persister.processUpdateGeneratedProperties(id, instance, state, session);
if (persister.isVersionPropertyGenerated()) {
nextVersion = Versioning.getVersion(state, persister);
}
}
// have the entity entry doAfterTransactionCompletion post-update processing, passing it the
// update state and the new version (if one).
entry.postUpdate(instance, state, nextVersion);
}
if (persister.hasCache()) {
if (persister.isCacheInvalidationRequired() || entry.getStatus() != Status.MANAGED) {
persister.getCacheAccessStrategy().remove(session, ck);
} else if (session.getCacheMode().isPutEnabled()) {
//TODO: inefficient if that cache is just going to ignore the updated state!
final CacheEntry ce = persister.buildCacheEntry(instance, state, nextVersion, getSession());
cacheEntry = persister.getCacheEntryStructure().structure(ce);
final boolean put = cacheUpdate(persister, previousVersion, ck);
if (put && factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().secondLevelCachePut(getPersister().getCacheAccessStrategy().getRegion().getName());
}
}
}
session.getPersistenceContext().getNaturalIdHelper().manageSharedNaturalIdCrossReference(persister, id, state, previousNaturalIdValues, CachedNaturalIdValueSource.UPDATE);
postUpdate();
if (factory.getStatistics().isStatisticsEnabled() && !veto) {
factory.getStatistics().updateEntity(getPersister().getEntityName());
}
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class AbstractPersistentCollection method getOrphans.
/**
* Given a collection of entity instances that used to
* belong to the collection, and a collection of instances
* that currently belong, return a collection of orphans
*/
@SuppressWarnings({ "JavaDoc", "unchecked" })
protected static Collection getOrphans(Collection oldElements, Collection currentElements, String entityName, SharedSessionContractImplementor session) throws HibernateException {
// short-circuit(s)
if (currentElements.size() == 0) {
// no new elements, the old list contains only Orphans
return oldElements;
}
if (oldElements.size() == 0) {
// no old elements, so no Orphans neither
return oldElements;
}
final EntityPersister entityPersister = session.getFactory().getEntityPersister(entityName);
final Type idType = entityPersister.getIdentifierType();
final boolean useIdDirect = mayUseIdDirect(idType);
// create the collection holding the Orphans
final Collection res = new ArrayList();
// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
final java.util.Set currentIds = new HashSet();
final java.util.Set currentSaving = new IdentitySet();
for (Object current : currentElements) {
if (current != null && ForeignKeys.isNotTransient(entityName, current, null, session)) {
final EntityEntry ee = session.getPersistenceContext().getEntry(current);
if (ee != null && ee.getStatus() == Status.SAVING) {
currentSaving.add(current);
} else {
final Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, current, session);
currentIds.add(useIdDirect ? currentId : new TypedValue(idType, currentId));
}
}
}
// iterate over the *old* list
for (Object old : oldElements) {
if (!currentSaving.contains(old)) {
final Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, old, session);
if (!currentIds.contains(useIdDirect ? oldId : new TypedValue(idType, oldId))) {
res.add(old);
}
}
}
return res;
}
Aggregations