Search in sources :

Example 26 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultReplicateEventListener method onReplicate.

/**
	 * Handle the given replicate event.
	 *
	 * @param event The replicate event to be handled.
	 *
	 * @throws TransientObjectException An invalid attempt to replicate a transient entity.
	 */
public void onReplicate(ReplicateEvent event) {
    final EventSource source = event.getSession();
    if (source.getPersistenceContext().reassociateIfUninitializedProxy(event.getObject())) {
        LOG.trace("Uninitialized proxy passed to replicate()");
        return;
    }
    Object entity = source.getPersistenceContext().unproxyAndReassociate(event.getObject());
    if (source.getPersistenceContext().isEntryFor(entity)) {
        LOG.trace("Ignoring persistent instance passed to replicate()");
        //hum ... should we cascade anyway? throw an exception? fine like it is?
        return;
    }
    EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
    // get the id from the object
    /*if ( persister.isUnsaved(entity, source) ) {
			throw new TransientObjectException("transient instance passed to replicate()");
		}*/
    Serializable id = persister.getIdentifier(entity, source);
    if (id == null) {
        throw new TransientObjectException("instance with null id passed to replicate()");
    }
    final ReplicationMode replicationMode = event.getReplicationMode();
    final Object oldVersion;
    if (replicationMode == ReplicationMode.EXCEPTION) {
        //always do an INSERT, and let it fail by constraint violation
        oldVersion = null;
    } else {
        //what is the version on the database?
        oldVersion = persister.getCurrentVersion(id, source);
    }
    final boolean traceEnabled = LOG.isTraceEnabled();
    if (oldVersion != null) {
        if (traceEnabled) {
            LOG.tracev("Found existing row for {0}", MessageHelper.infoString(persister, id, source.getFactory()));
        }
        /// HHH-2378
        final Object realOldVersion = persister.isVersioned() ? oldVersion : null;
        boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(entity, realOldVersion, persister.getVersion(entity), persister.getVersionType());
        // else do nothing (don't even reassociate object!)
        if (canReplicate) {
            performReplication(entity, id, realOldVersion, persister, replicationMode, source);
        } else if (traceEnabled) {
            LOG.trace("No need to replicate");
        }
    //TODO: would it be better to do a refresh from db?
    } else {
        // no existing row - do an insert
        if (traceEnabled) {
            LOG.tracev("No existing row, replicating new instance {0}", MessageHelper.infoString(persister, id, source.getFactory()));
        }
        // prefer re-generation of identity!
        final boolean regenerate = persister.isIdentifierAssignedByInsert();
        final EntityKey key = regenerate ? null : source.generateEntityKey(id, persister);
        performSaveOrReplicate(entity, key, persister, regenerate, replicationMode, source, true);
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) TransientObjectException(org.hibernate.TransientObjectException) EntityKey(org.hibernate.engine.spi.EntityKey) EventSource(org.hibernate.event.spi.EventSource) Serializable(java.io.Serializable) ReplicationMode(org.hibernate.ReplicationMode)

Example 27 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultLoadEventListener method assembleCacheEntry.

private Object assembleCacheEntry(final StandardCacheEntryImpl entry, final Serializable id, final EntityPersister persister, final LoadEvent event) throws HibernateException {
    final Object optionalObject = event.getInstanceToLoad();
    final EventSource session = event.getSession();
    final SessionFactoryImplementor factory = session.getFactory();
    if (traceEnabled) {
        LOG.tracev("Assembling entity from second-level cache: {0}", MessageHelper.infoString(persister, id, factory));
    }
    EntityPersister subclassPersister = factory.getEntityPersister(entry.getSubclass());
    Object result = optionalObject == null ? session.instantiate(subclassPersister, id) : optionalObject;
    // make it circular-reference safe
    final EntityKey entityKey = session.generateEntityKey(id, subclassPersister);
    TwoPhaseLoad.addUninitializedCachedEntity(entityKey, result, subclassPersister, LockMode.NONE, entry.getVersion(), session);
    Type[] types = subclassPersister.getPropertyTypes();
    Object[] values = entry.assemble(result, id, subclassPersister, session.getInterceptor(), session);
    // intializes result by side-effect
    TypeHelper.deepCopy(values, types, subclassPersister.getPropertyUpdateability(), values, session);
    Object version = Versioning.getVersion(values, subclassPersister);
    LOG.tracev("Cached Version: {0}", version);
    final PersistenceContext persistenceContext = session.getPersistenceContext();
    boolean isReadOnly = session.isDefaultReadOnly();
    if (persister.isMutable()) {
        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 = true;
    }
    persistenceContext.addEntry(result, (isReadOnly ? Status.READ_ONLY : Status.MANAGED), values, null, id, version, LockMode.NONE, true, subclassPersister, false);
    subclassPersister.afterInitialize(result, session);
    persistenceContext.initializeNonLazyCollections();
    // upgrade the lock if necessary:
    //lock(result, lockMode);
    //PostLoad is needed for EJB3
    //TODO: reuse the PostLoadEvent...
    PostLoadEvent postLoadEvent = event.getPostLoadEvent().setEntity(result).setId(id).setPersister(persister);
    for (PostLoadEventListener listener : postLoadEventListeners(session)) {
        listener.onPostLoad(postLoadEvent);
    }
    return result;
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) PostLoadEvent(org.hibernate.event.spi.PostLoadEvent) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) StatefulPersistenceContext(org.hibernate.engine.internal.StatefulPersistenceContext) HibernateProxy(org.hibernate.proxy.HibernateProxy) PostLoadEventListener(org.hibernate.event.spi.PostLoadEventListener) EntityKey(org.hibernate.engine.spi.EntityKey) EventSource(org.hibernate.event.spi.EventSource) EmbeddedComponentType(org.hibernate.type.EmbeddedComponentType) EntityType(org.hibernate.type.EntityType) EventType(org.hibernate.event.spi.EventType) Type(org.hibernate.type.Type)

Example 28 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultLockEventListener method onLock.

/**
	 * Handle the given lock event.
	 *
	 * @param event The lock event to be handled.
	 * @throws HibernateException
	 */
public void onLock(LockEvent event) throws HibernateException {
    if (event.getObject() == null) {
        throw new NullPointerException("attempted to lock null");
    }
    if (event.getLockMode() == LockMode.WRITE) {
        throw new HibernateException("Invalid lock mode for lock()");
    }
    if (event.getLockMode() == LockMode.UPGRADE_SKIPLOCKED) {
        LOG.explicitSkipLockedLockCombo();
    }
    SessionImplementor source = event.getSession();
    Object entity = source.getPersistenceContext().unproxyAndReassociate(event.getObject());
    //TODO: if object was an uninitialized proxy, this is inefficient,
    //      resulting in two SQL selects
    EntityEntry entry = source.getPersistenceContext().getEntry(entity);
    if (entry == null) {
        final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
        final Serializable id = persister.getIdentifier(entity, source);
        if (!ForeignKeys.isNotTransient(event.getEntityName(), entity, Boolean.FALSE, source)) {
            throw new TransientObjectException("cannot lock an unsaved transient instance: " + persister.getEntityName());
        }
        entry = reassociate(event, entity, id, persister);
        cascadeOnLock(event, persister, entity);
    }
    upgradeLock(entity, entry, event.getLockOptions(), event.getSession());
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) TransientObjectException(org.hibernate.TransientObjectException) EntityEntry(org.hibernate.engine.spi.EntityEntry) Serializable(java.io.Serializable) HibernateException(org.hibernate.HibernateException) SessionImplementor(org.hibernate.engine.spi.SessionImplementor)

Example 29 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultMergeEventListener method entityIsDetached.

protected void entityIsDetached(MergeEvent event, Map copyCache) {
    LOG.trace("Merging detached instance");
    final Object entity = event.getEntity();
    final EventSource source = event.getSession();
    final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
    final String entityName = persister.getEntityName();
    Serializable id = event.getRequestedId();
    if (id == null) {
        id = persister.getIdentifier(entity, source);
    } else {
        // check that entity id = requestedId
        Serializable entityId = persister.getIdentifier(entity, source);
        if (!persister.getIdentifierType().isEqual(id, entityId, source.getFactory())) {
            throw new HibernateException("merge requested with id not matching id of passed entity");
        }
    }
    String previousFetchProfile = source.getLoadQueryInfluencers().getInternalFetchProfile();
    source.getLoadQueryInfluencers().setInternalFetchProfile("merge");
    //we must clone embedded composite identifiers, or
    //we will get back the same instance that we pass in
    final Serializable clonedIdentifier = (Serializable) persister.getIdentifierType().deepCopy(id, source.getFactory());
    final Object result = source.get(entityName, clonedIdentifier);
    source.getLoadQueryInfluencers().setInternalFetchProfile(previousFetchProfile);
    if (result == null) {
        //TODO: we should throw an exception if we really *know* for sure
        //      that this is a detached instance, rather than just assuming
        //throw new StaleObjectStateException(entityName, id);
        // we got here because we assumed that an instance
        // with an assigned id was detached, when it was
        // really persistent
        entityIsTransient(event, copyCache);
    } else {
        //beforeQuery cascade!
        ((MergeContext) copyCache).put(entity, result, true);
        final Object target = source.getPersistenceContext().unproxy(result);
        if (target == entity) {
            throw new AssertionFailure("entity was not detached");
        } else if (!source.getEntityName(target).equals(entityName)) {
            throw new WrongClassException("class of the given object did not match class of persistent copy", event.getRequestedId(), entityName);
        } else if (isVersionChanged(entity, source, persister, target)) {
            if (source.getFactory().getStatistics().isStatisticsEnabled()) {
                source.getFactory().getStatisticsImplementor().optimisticFailure(entityName);
            }
            throw new StaleObjectStateException(entityName, id);
        }
        // cascade first, so that all unsaved objects get their
        // copy created beforeQuery we actually copy
        cascadeOnMerge(source, persister, entity, copyCache);
        copyValues(persister, entity, target, source, copyCache);
        //copyValues works by reflection, so explicitly mark the entity instance dirty
        markInterceptorDirty(entity, target, persister);
        event.setResult(result);
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EventSource(org.hibernate.event.spi.EventSource) Serializable(java.io.Serializable) AssertionFailure(org.hibernate.AssertionFailure) HibernateException(org.hibernate.HibernateException) WrongClassException(org.hibernate.WrongClassException) StaleObjectStateException(org.hibernate.StaleObjectStateException)

Example 30 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultMergeEventListener method entityIsTransient.

protected void entityIsTransient(MergeEvent event, Map copyCache) {
    LOG.trace("Merging transient instance");
    final Object entity = event.getEntity();
    final EventSource source = event.getSession();
    final String entityName = event.getEntityName();
    final EntityPersister persister = source.getEntityPersister(entityName, entity);
    final Serializable id = persister.hasIdentifierProperty() ? persister.getIdentifier(entity, source) : null;
    if (copyCache.containsKey(entity)) {
        persister.setIdentifier(copyCache.get(entity), id, source);
    } else {
        //beforeQuery cascade!
        ((MergeContext) copyCache).put(entity, source.instantiate(persister, id), true);
    }
    final Object copy = copyCache.get(entity);
    // cascade first, so that all unsaved objects get their
    // copy created beforeQuery we actually copy
    //cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
    super.cascadeBeforeSave(source, persister, entity, copyCache);
    copyValues(persister, entity, copy, source, copyCache, ForeignKeyDirection.FROM_PARENT);
    saveTransientEntity(copy, entityName, event.getRequestedId(), source, copyCache);
    // cascade first, so that all unsaved objects get their
    // copy created beforeQuery we actually copy
    super.cascadeAfterSave(source, persister, entity, copyCache);
    copyValues(persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT);
    event.setResult(copy);
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EventSource(org.hibernate.event.spi.EventSource) Serializable(java.io.Serializable)

Aggregations

EntityPersister (org.hibernate.persister.entity.EntityPersister)166 Test (org.junit.Test)59 Serializable (java.io.Serializable)34 Session (org.hibernate.Session)31 Type (org.hibernate.type.Type)29 EntityEntry (org.hibernate.engine.spi.EntityEntry)21 EventSource (org.hibernate.event.spi.EventSource)15 EntityRegionAccessStrategy (org.hibernate.cache.spi.access.EntityRegionAccessStrategy)13 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)13 TestForIssue (org.hibernate.testing.TestForIssue)13 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)12 SequenceStyleGenerator (org.hibernate.id.enhanced.SequenceStyleGenerator)12 EntityType (org.hibernate.type.EntityType)12 ArrayList (java.util.ArrayList)11 CompositeType (org.hibernate.type.CompositeType)11 HibernateProxy (org.hibernate.proxy.HibernateProxy)10 PreparedStatement (java.sql.PreparedStatement)8 List (java.util.List)8 EntityKey (org.hibernate.engine.spi.EntityKey)8 QueryParameters (org.hibernate.engine.spi.QueryParameters)8