Skip to content

Commit

Permalink
HHH-7841 - Redesign Loader
Browse files Browse the repository at this point in the history
  • Loading branch information
sebersole committed Apr 11, 2013
1 parent 88d5c02 commit 3f8699c
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 114 deletions.
Expand Up @@ -187,22 +187,31 @@ public void checkVersion(
EntityPersister persister,
EntityAliases entityAliases,
EntityKey entityKey,
Object entityInstance) throws SQLException {
Object entityInstance) {
final Object version = session.getPersistenceContext().getEntry( entityInstance ).getVersion();

if ( version != null ) {
//null version means the object is in the process of being loaded somewhere else in the ResultSet
VersionType versionType = persister.getVersionType();
Object currentVersion = versionType.nullSafeGet(
resultSet,
entityAliases.getSuffixedVersionAliases(),
session,
null
);
if ( !versionType.isEqual(version, currentVersion) ) {
final Object currentVersion;
try {
currentVersion = versionType.nullSafeGet(
resultSet,
entityAliases.getSuffixedVersionAliases(),
session,
null
);
}
catch (SQLException e) {
throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
e,
"Could not read version value from result set"
);
}

if ( !versionType.isEqual( version, currentVersion ) ) {
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatisticsImplementor()
.optimisticFailure( persister.getEntityName() );
session.getFactory().getStatisticsImplementor().optimisticFailure( persister.getEntityName() );
}
throw new StaleObjectStateException( persister.getEntityName(), entityKey.getIdentifier() );
}
Expand All @@ -214,19 +223,28 @@ public String getConcreteEntityTypeName(
final ResultSet rs,
final EntityPersister persister,
final EntityAliases entityAliases,
final EntityKey entityKey) throws SQLException {
final EntityKey entityKey) {

final Loadable loadable = (Loadable) persister;
if ( ! loadable.hasSubclasses() ) {
return persister.getEntityName();
}

final Object discriminatorValue = loadable.getDiscriminatorType().nullSafeGet(
rs,
entityAliases.getSuffixedDiscriminatorAlias(),
session,
null
);
final Object discriminatorValue;
try {
discriminatorValue = loadable.getDiscriminatorType().nullSafeGet(
rs,
entityAliases.getSuffixedDiscriminatorAlias(),
session,
null
);
}
catch (SQLException e) {
throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
e,
"Could not read discriminator value from ResultSet"
);
}

final String result = loadable.getSubclassForDiscriminatorValue( discriminatorValue );

Expand All @@ -242,6 +260,90 @@ public String getConcreteEntityTypeName(
return result;
}

@Override
public Object resolveEntityKey(EntityKey entityKey, EntityKeyResolutionContext entityKeyContext) {
final Object existing = getSession().getEntityUsingInterceptor( entityKey );

if ( existing != null ) {
if ( !entityKeyContext.getEntityPersister().isInstance( existing ) ) {
throw new WrongClassException(
"loaded object was of wrong class " + existing.getClass(),
entityKey.getIdentifier(),
entityKeyContext.getEntityPersister().getEntityName()
);
}

final LockMode requestedLockMode = entityKeyContext.getLockMode() == null
? LockMode.NONE
: entityKeyContext.getLockMode();

if ( requestedLockMode != LockMode.NONE ) {
final LockMode currentLockMode = getSession().getPersistenceContext().getEntry( existing ).getLockMode();
final boolean isVersionCheckNeeded = entityKeyContext.getEntityPersister().isVersioned()
&& currentLockMode.lessThan( requestedLockMode );

// 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(
resultSet,
entityKeyContext.getEntityPersister(),
entityKeyContext.getEntityAliases(),
entityKey,
existing
);
//we need to upgrade the lock mode to the mode requested
getSession().getPersistenceContext().getEntry( existing ).setLockMode( requestedLockMode );
}
}

return existing;
}
else {
final String concreteEntityTypeName = getConcreteEntityTypeName(
resultSet,
entityKeyContext.getEntityPersister(),
entityKeyContext.getEntityAliases(),
entityKey
);

final Object entityInstance = getSession().instantiate(
concreteEntityTypeName,
entityKey.getIdentifier()
);

//need to hydrate it.

// grab its state from the ResultSet and keep it in the Session
// (but don't yet initialize the object itself)
// note that we acquire LockMode.READ even if it was not requested
final LockMode requestedLockMode = entityKeyContext.getLockMode() == null
? LockMode.NONE
: entityKeyContext.getLockMode();
final LockMode acquiredLockMode = requestedLockMode == LockMode.NONE
? LockMode.READ
: requestedLockMode;

loadFromResultSet(
resultSet,
entityInstance,
concreteEntityTypeName,
entityKey,
entityKeyContext.getEntityAliases(),
acquiredLockMode,
entityKeyContext.getEntityPersister(),
true,
entityKeyContext.getEntityPersister().getEntityMetamodel().getEntityType()
);

// materialize associations (and initialize the object) later
registerHydratedEntity( entityKeyContext.getEntityPersister(), entityKey, entityInstance );

return entityInstance;
}
}

@Override
public void loadFromResultSet(
ResultSet resultSet,
Expand All @@ -252,7 +354,7 @@ public void loadFromResultSet(
LockMode acquiredLockMode,
EntityPersister rootPersister,
boolean eagerFetch,
EntityType associationType) throws SQLException {
EntityType associationType) {

final Serializable id = entityKey.getIdentifier();

Expand Down Expand Up @@ -287,17 +389,35 @@ public void loadFromResultSet(
entityAliases.getSuffixedPropertyAliases() :
entityAliases.getSuffixedPropertyAliases(persister);

final Object[] values = persister.hydrate(
resultSet,
id,
entityInstance,
(Loadable) rootPersister,
cols,
eagerFetch,
session
);
final Object[] values;
try {
values = persister.hydrate(
resultSet,
id,
entityInstance,
(Loadable) rootPersister,
cols,
eagerFetch,
session
);
}
catch (SQLException e) {
throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
e,
"Could not read entity state from ResultSet : " + entityKey
);
}

final Object rowId = persister.hasRowId() ? resultSet.getObject( entityAliases.getRowIdAlias() ) : null;
final Object rowId;
try {
rowId = persister.hasRowId() ? resultSet.getObject( entityAliases.getRowIdAlias() ) : null;
}
catch (SQLException e) {
throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
e,
"Could not read entity row-id from ResultSet : " + entityKey
);
}

if ( associationType != null ) {
String ukName = associationType.getRHSUniqueKeyPropertyName();
Expand Down
Expand Up @@ -28,7 +28,6 @@

import org.hibernate.AssertionFailure;
import org.hibernate.LockMode;
import org.hibernate.WrongClassException;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor;
Expand All @@ -45,7 +44,10 @@
/**
* @author Steve Ebersole
*/
public class EntityReturn extends AbstractFetchOwner implements Return, FetchOwner, EntityReference {
public class EntityReturn
extends AbstractFetchOwner
implements Return, FetchOwner, EntityReference, ResultSetProcessingContext.EntityKeyResolutionContext {

private final EntityAliases entityAliases;
private final String sqlTableAlias;

Expand Down Expand Up @@ -180,76 +182,7 @@ public Object read(ResultSet resultSet, ResultSetProcessingContext context) thro
throw new AssertionFailure( "Could not locate resolved EntityKey");
}

final Object existing = context.getSession().getEntityUsingInterceptor( entityKey );

if ( existing != null ) {
if ( !persister.isInstance( existing ) ) {
throw new WrongClassException(
"loaded object was of wrong class " + existing.getClass(),
entityKey.getIdentifier(),
persister.getEntityName()
);
}

if ( getLockMode() != null && getLockMode() != LockMode.NONE ) {
final boolean isVersionCheckNeeded = persister.isVersioned()
&& context.getSession().getPersistenceContext().getEntry( existing ).getLockMode().lessThan( getLockMode() );

// 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
context.checkVersion(
resultSet,
persister,
entityAliases,
entityKey,
existing
);
//we need to upgrade the lock mode to the mode requested
context.getSession().getPersistenceContext().getEntry( existing ).setLockMode( getLockMode() );
}
}

return existing;
}
else {
final String concreteEntityTypeName = context.getConcreteEntityTypeName(
resultSet,
persister,
entityAliases,
entityKey
);

final Object entityInstance = context.getSession().instantiate(
concreteEntityTypeName,
entityKey.getIdentifier()
);

//need to hydrate it.

// grab its state from the ResultSet and keep it in the Session
// (but don't yet initialize the object itself)
// note that we acquire LockMode.READ even if it was not requested
LockMode acquiredLockMode = getLockMode() == LockMode.NONE ? LockMode.READ : getLockMode();

context.loadFromResultSet(
resultSet,
entityInstance,
concreteEntityTypeName,
entityKey,
entityAliases,
acquiredLockMode,
persister,
true,
persister.getEntityMetamodel().getEntityType()
);

// materialize associations (and initialize the object) later
context.registerHydratedEntity( persister, entityKey, entityInstance );

return entityInstance;
}
return context.resolveEntityKey( entityKey, this );
}

@Override
Expand Down
Expand Up @@ -27,7 +27,7 @@
* The context for named parameters.
* <p/>
* NOTE : the hope with the SQL-redesign stuff is that this whole concept goes away, the idea being that
* the parameters are encoded into the query tree and "bind themselves".
* the parameters are encoded into the query tree and "bind themselves"; see {@link org.hibernate.param.ParameterSpecification}.
*
* @author Steve Ebersole
*/
Expand Down

This file was deleted.

Expand Up @@ -23,20 +23,16 @@
*/
package org.hibernate.loader.spi;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.LockMode;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.Return;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;

/**
Expand All @@ -49,8 +45,6 @@ public interface ResultSetProcessingContext {

public EntityKey getDictatedRootEntityKey();

public IdentifierResolutionContext getIdentifierResolutionContext(EntityReference entityReference);

public static interface IdentifierResolutionContext {
public EntityReference getEntityReference();

Expand All @@ -63,8 +57,21 @@ public static interface IdentifierResolutionContext {
public EntityKey getEntityKey();
}

public IdentifierResolutionContext getIdentifierResolutionContext(EntityReference entityReference);

public void registerHydratedEntity(EntityPersister persister, EntityKey entityKey, Object entityInstance);

public static interface EntityKeyResolutionContext {
public EntityPersister getEntityPersister();
public LockMode getLockMode();
public EntityAliases getEntityAliases();
}

public Object resolveEntityKey(EntityKey entityKey, EntityKeyResolutionContext entityKeyContext);


// should be able to get rid of the methods below here from the interface ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public void checkVersion(
ResultSet resultSet,
EntityPersister persister,
Expand Down

0 comments on commit 3f8699c

Please sign in to comment.