/** * The entity instance is already in the session cache */ private void instanceAlreadyLoaded( final ResultSet rs, final int i, final Loadable persister, final EntityKey key, final Object object, final LockMode requestedLockMode, final SessionImplementor session) throws HibernateException, SQLException { if ( !persister.isInstance( object ) ) { throw new WrongClassException( "loaded object was of wrong class " + object.getClass(), key.getIdentifier(), persister.getEntityName() ); } if ( LockMode.NONE != requestedLockMode && upgradeLocks() ) { //no point doing this if NONE was requested final EntityEntry entry = session.getPersistenceContext().getEntry( object ); if ( entry.getLockMode().lessThan( requestedLockMode ) ) { //we only check the version when _upgrading_ lock modes if ( persister.isVersioned() ) { checkVersion( i, persister, key.getIdentifier(), object, rs, session ); } //we need to upgrade the lock mode to the mode requested entry.setLockMode( requestedLockMode ); } } }
/** * Determine the concrete class of an instance in the <tt>ResultSet</tt> */ private String getInstanceClass( final ResultSet rs, final int i, final Loadable persister, final Serializable id, final SessionImplementor session) throws HibernateException, SQLException { if ( persister.hasSubclasses() ) { // Code to handle subclasses of topClass Object discriminatorValue = persister.getDiscriminatorType().nullSafeGet( rs, getEntityAliases()[i].getSuffixedDiscriminatorAlias(), session, null ); final String result = persister.getSubclassForDiscriminatorValue( discriminatorValue ); if ( result == null ) { //woops we got an instance of another class hierarchy branch throw new WrongClassException( "Discriminator: " + discriminatorValue, id, persister.getEntityName() ); } return result; } else { return persister.getEntityName(); } }
private String getConcreteEntityTypeName( ResultSet resultSet, ResultSetProcessingContext context, EntityKey entityKey) { final Loadable loadable = (Loadable) entityReference.getEntityPersister(); if ( ! loadable.hasSubclasses() ) { return entityReference.getEntityPersister().getEntityName(); } final Object discriminatorValue; try { discriminatorValue = loadable.getDiscriminatorType().nullSafeGet( resultSet, entityReferenceAliases.getColumnAliases().getSuffixedDiscriminatorAlias(), context.getSession(), null ); } catch (SQLException e) { throw context.getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert( e, "Could not read discriminator value from ResultSet" ); } final String result = loadable.getSubclassForDiscriminatorValue( discriminatorValue ); if ( result == null ) { // whoops! we got an instance of another class hierarchy branch throw new WrongClassException( "Discriminator: " + discriminatorValue, entityKey.getIdentifier(), entityReference.getEntityPersister().getEntityName() ); } return result; }
/** * The entity instance is already in the session cache */ private void instanceAlreadyLoaded( final ResultSet rs, final int i, final Loadable persister, final EntityKey key, final Object object, final LockMode lockMode, final SessionImplementor session) throws HibernateException, SQLException { if ( !persister.isInstance( object, session.getEntityMode() ) ) { throw new WrongClassException( "loaded object was of wrong class " + object.getClass(), key.getIdentifier(), persister.getEntityName() ); } if ( LockMode.NONE != lockMode && upgradeLocks() ) { //no point doing this if NONE was requested final boolean isVersionCheckNeeded = persister.isVersioned() && session.getPersistenceContext().getEntry(object) .getLockMode().lessThan( lockMode ); // we don't need to worry about existing version being uninitialized // because this block isn't called by a re-entrant load (re-entrant // loads _always_ have lock mode NONE) if (isVersionCheckNeeded) { //we only check the version when _upgrading_ lock modes checkVersion( i, persister, key.getIdentifier(), object, rs, session ); //we need to upgrade the lock mode to the mode requested session.getPersistenceContext().getEntry(object) .setLockMode(lockMode); } } }
public HibernateObjectRetrievalFailureException(WrongClassException ex) { super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex); }
/** * Attempts to load the entity from the second-level cache. * * @param event The load event * @param persister The persister for the entity being requested for load * @param options The load options. * * @return The entity from the second-level cache, or null. */ protected Object loadFromSecondLevelCache( final LoadEvent event, final EntityPersister persister, final LoadEventListener.LoadType options) { final SessionImplementor source = event.getSession(); final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled() && event.getLockMode().lessThan( LockMode.READ ); if ( !useCache ) { // we can't use cache here return null; } final SessionFactoryImplementor factory = source.getFactory(); final CacheKey ck = source.generateCacheKey( event.getEntityId(), persister.getIdentifierType(), persister.getRootEntityName() ); final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() ); if ( factory.getStatistics().isStatisticsEnabled() ) { if ( ce == null ) { factory.getStatisticsImplementor().secondLevelCacheMiss( persister.getCacheAccessStrategy().getRegion().getName() ); } else { factory.getStatisticsImplementor().secondLevelCacheHit( persister.getCacheAccessStrategy().getRegion().getName() ); } } if ( ce == null ) { // nothing was found in cache return null; } CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory ); Object entity = convertCacheEntryToEntity( entry, event.getEntityId(), persister, event ); if ( !persister.isInstance( entity ) ) { throw new WrongClassException( "loaded object was of wrong class " + entity.getClass(), event.getEntityId(), persister.getEntityName() ); } return entity; }
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.getFetchProfile(); source.setFetchProfile( "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.setFetchProfile( 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 { ( (MergeContext) copyCache ).put( entity, result, true ); //before cascade! 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 before 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 ); } }
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.getEntityMode() ); } else { // check that entity id = requestedId Serializable entityId = persister.getIdentifier( entity, source.getEntityMode() ); if ( !persister.getIdentifierType().isEqual( id, entityId, source.getEntityMode(), source.getFactory() ) ) { throw new HibernateException( "merge requested with id not matching id of passed entity" ); } } String previousFetchProfile = source.getFetchProfile(); source.setFetchProfile("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.getEntityMode(), source.getFactory() ); final Object result = source.get(entityName, clonedIdentifier); source.setFetchProfile(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 { copyCache.put(entity, result); //before cascade! 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 before 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 ); event.setResult(result); } }