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;
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class StatefulPersistenceContext method addEntry.
@Override
public EntityEntry addEntry(final Object entity, final Status status, final Object[] loadedState, final Object rowId, final Serializable id, final Object version, final LockMode lockMode, final boolean existsInDatabase, final EntityPersister persister, final boolean disableVersionIncrement) {
final EntityEntry e;
/*
IMPORTANT!!!
The following instanceof checks and castings are intentional.
DO NOT REFACTOR to make calls through the EntityEntryFactory interface, which would result
in polymorphic call sites which will severely impact performance.
When a virtual method is called via an interface the JVM needs to resolve which concrete
implementation to call. This takes CPU cycles and is a performance penalty. It also prevents method
in-ling which further degrades performance. Casting to an implementation and making a direct method call
removes the virtual call, and allows the methods to be in-lined. In this critical code path, it has a very
large impact on performance to make virtual method calls.
*/
if (persister.getEntityEntryFactory() instanceof MutableEntityEntryFactory) {
// noinspection RedundantCast
e = ((MutableEntityEntryFactory) persister.getEntityEntryFactory()).createEntityEntry(status, loadedState, rowId, id, version, lockMode, existsInDatabase, persister, disableVersionIncrement, this);
} else {
// noinspection RedundantCast
e = ((ImmutableEntityEntryFactory) persister.getEntityEntryFactory()).createEntityEntry(status, loadedState, rowId, id, version, lockMode, existsInDatabase, persister, disableVersionIncrement, this);
}
entityEntryContext.addEntityEntry(entity, e);
setHasNonReadOnlyEnties(status);
return e;
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class TwoPhaseLoad method initializeEntity.
/**
* Perform the second step of 2-phase load. Fully initialize the entity
* instance.
* <p/>
* After processing a JDBC result set, we "resolve" all the associations
* between the entities which were instantiated and had their state
* "hydrated" into an array
*
* @param entity The entity being loaded
* @param readOnly Is the entity being loaded as read-only
* @param session The Session
* @param preLoadEvent The (re-used) pre-load event
*/
public static void initializeEntity(final Object entity, final boolean readOnly, final SharedSessionContractImplementor session, final PreLoadEvent preLoadEvent) {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entityEntry = persistenceContext.getEntry(entity);
if (entityEntry == null) {
throw new AssertionFailure("possible non-threadsafe access to the session");
}
doInitializeEntity(entity, entityEntry, readOnly, session, preLoadEvent);
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class DefaultFlushEntityEventListener method handleInterception.
protected boolean handleInterception(FlushEntityEvent event) {
SessionImplementor session = event.getSession();
EntityEntry entry = event.getEntityEntry();
EntityPersister persister = entry.getPersister();
Object entity = event.getEntity();
// give the Interceptor a chance to modify property values
final Object[] values = event.getPropertyValues();
final boolean intercepted = invokeInterceptor(session, entity, entry, values, persister);
// now we might need to recalculate the dirtyProperties array
if (intercepted && event.isDirtyCheckPossible() && !event.isDirtyCheckHandledByInterceptor()) {
int[] dirtyProperties;
if (event.hasDatabaseSnapshot()) {
dirtyProperties = persister.findModified(event.getDatabaseSnapshot(), values, entity, session);
} else {
dirtyProperties = persister.findDirty(values, entry.getLoadedState(), entity, session);
}
event.setDirtyProperties(dirtyProperties);
}
return intercepted;
}
use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.
the class DefaultPersistEventListener method onPersist.
/**
* Handle the given create event.
*
* @param event The create event to be handled.
*/
public void onPersist(PersistEvent event, Map createCache) throws HibernateException {
final SessionImplementor source = event.getSession();
final Object object = event.getObject();
final Object entity;
if (object instanceof HibernateProxy) {
LazyInitializer li = ((HibernateProxy) object).getHibernateLazyInitializer();
if (li.isUninitialized()) {
if (li.getSession() == source) {
// NOTE EARLY EXIT!
return;
} else {
throw new PersistentObjectException("uninitialized proxy passed to persist()");
}
}
entity = li.getImplementation();
} else {
entity = object;
}
final String entityName;
if (event.getEntityName() != null) {
entityName = event.getEntityName();
} else {
entityName = source.bestGuessEntityName(entity);
event.setEntityName(entityName);
}
final EntityEntry entityEntry = source.getPersistenceContext().getEntry(entity);
EntityState entityState = getEntityState(entity, entityName, entityEntry, source);
if (entityState == EntityState.DETACHED) {
// JPA 2, in its version of a "foreign generated", allows the id attribute value
// to be manually set by the user, even though this manual value is irrelevant.
// The issue is that this causes problems with the Hibernate unsaved-value strategy
// which comes into play here in determining detached/transient state.
//
// Detect if we have this situation and if so null out the id value and calculate the
// entity state again.
// NOTE: entityEntry must be null to get here, so we cannot use any of its values
EntityPersister persister = source.getFactory().getEntityPersister(entityName);
if (ForeignGenerator.class.isInstance(persister.getIdentifierGenerator())) {
if (LOG.isDebugEnabled() && persister.getIdentifier(entity, source) != null) {
LOG.debug("Resetting entity id attribute to null for foreign generator");
}
persister.setIdentifier(entity, null, source);
entityState = getEntityState(entity, entityName, entityEntry, source);
}
}
switch(entityState) {
case DETACHED:
{
throw new PersistentObjectException("detached entity passed to persist: " + getLoggableName(event.getEntityName(), entity));
}
case PERSISTENT:
{
entityIsPersistent(event, createCache);
break;
}
case TRANSIENT:
{
entityIsTransient(event, createCache);
break;
}
case DELETED:
{
entityEntry.setStatus(Status.MANAGED);
entityEntry.setDeletedState(null);
event.getSession().getActionQueue().unScheduleDeletion(entityEntry, event.getObject());
entityIsDeleted(event, createCache);
break;
}
default:
{
throw new ObjectDeletedException("deleted entity passed to persist", null, getLoggableName(event.getEntityName(), entity));
}
}
}
Aggregations