HHH-7841 - Redesign Loader
This commit is contained in:
parent
88d5c02d7f
commit
3f8699c913
|
@ -187,22 +187,31 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
EntityPersister persister,
|
EntityPersister persister,
|
||||||
EntityAliases entityAliases,
|
EntityAliases entityAliases,
|
||||||
EntityKey entityKey,
|
EntityKey entityKey,
|
||||||
Object entityInstance) throws SQLException {
|
Object entityInstance) {
|
||||||
final Object version = session.getPersistenceContext().getEntry( entityInstance ).getVersion();
|
final Object version = session.getPersistenceContext().getEntry( entityInstance ).getVersion();
|
||||||
|
|
||||||
if ( version != null ) {
|
if ( version != null ) {
|
||||||
//null version means the object is in the process of being loaded somewhere else in the ResultSet
|
//null version means the object is in the process of being loaded somewhere else in the ResultSet
|
||||||
VersionType versionType = persister.getVersionType();
|
VersionType versionType = persister.getVersionType();
|
||||||
Object currentVersion = versionType.nullSafeGet(
|
final Object currentVersion;
|
||||||
resultSet,
|
try {
|
||||||
entityAliases.getSuffixedVersionAliases(),
|
currentVersion = versionType.nullSafeGet(
|
||||||
session,
|
resultSet,
|
||||||
null
|
entityAliases.getSuffixedVersionAliases(),
|
||||||
);
|
session,
|
||||||
if ( !versionType.isEqual(version, currentVersion) ) {
|
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() ) {
|
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||||
session.getFactory().getStatisticsImplementor()
|
session.getFactory().getStatisticsImplementor().optimisticFailure( persister.getEntityName() );
|
||||||
.optimisticFailure( persister.getEntityName() );
|
|
||||||
}
|
}
|
||||||
throw new StaleObjectStateException( persister.getEntityName(), entityKey.getIdentifier() );
|
throw new StaleObjectStateException( persister.getEntityName(), entityKey.getIdentifier() );
|
||||||
}
|
}
|
||||||
|
@ -214,19 +223,28 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
final ResultSet rs,
|
final ResultSet rs,
|
||||||
final EntityPersister persister,
|
final EntityPersister persister,
|
||||||
final EntityAliases entityAliases,
|
final EntityAliases entityAliases,
|
||||||
final EntityKey entityKey) throws SQLException {
|
final EntityKey entityKey) {
|
||||||
|
|
||||||
final Loadable loadable = (Loadable) persister;
|
final Loadable loadable = (Loadable) persister;
|
||||||
if ( ! loadable.hasSubclasses() ) {
|
if ( ! loadable.hasSubclasses() ) {
|
||||||
return persister.getEntityName();
|
return persister.getEntityName();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object discriminatorValue = loadable.getDiscriminatorType().nullSafeGet(
|
final Object discriminatorValue;
|
||||||
rs,
|
try {
|
||||||
entityAliases.getSuffixedDiscriminatorAlias(),
|
discriminatorValue = loadable.getDiscriminatorType().nullSafeGet(
|
||||||
session,
|
rs,
|
||||||
null
|
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 );
|
final String result = loadable.getSubclassForDiscriminatorValue( discriminatorValue );
|
||||||
|
|
||||||
|
@ -242,6 +260,90 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
return result;
|
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
|
@Override
|
||||||
public void loadFromResultSet(
|
public void loadFromResultSet(
|
||||||
ResultSet resultSet,
|
ResultSet resultSet,
|
||||||
|
@ -252,7 +354,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
LockMode acquiredLockMode,
|
LockMode acquiredLockMode,
|
||||||
EntityPersister rootPersister,
|
EntityPersister rootPersister,
|
||||||
boolean eagerFetch,
|
boolean eagerFetch,
|
||||||
EntityType associationType) throws SQLException {
|
EntityType associationType) {
|
||||||
|
|
||||||
final Serializable id = entityKey.getIdentifier();
|
final Serializable id = entityKey.getIdentifier();
|
||||||
|
|
||||||
|
@ -287,17 +389,35 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
entityAliases.getSuffixedPropertyAliases() :
|
entityAliases.getSuffixedPropertyAliases() :
|
||||||
entityAliases.getSuffixedPropertyAliases(persister);
|
entityAliases.getSuffixedPropertyAliases(persister);
|
||||||
|
|
||||||
final Object[] values = persister.hydrate(
|
final Object[] values;
|
||||||
resultSet,
|
try {
|
||||||
id,
|
values = persister.hydrate(
|
||||||
entityInstance,
|
resultSet,
|
||||||
(Loadable) rootPersister,
|
id,
|
||||||
cols,
|
entityInstance,
|
||||||
eagerFetch,
|
(Loadable) rootPersister,
|
||||||
session
|
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 ) {
|
if ( associationType != null ) {
|
||||||
String ukName = associationType.getRHSUniqueKeyPropertyName();
|
String ukName = associationType.getRHSUniqueKeyPropertyName();
|
||||||
|
|
|
@ -28,7 +28,6 @@ import java.sql.SQLException;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.WrongClassException;
|
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
@ -45,7 +44,10 @@ import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierReso
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @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 EntityAliases entityAliases;
|
||||||
private final String sqlTableAlias;
|
private final String sqlTableAlias;
|
||||||
|
|
||||||
|
@ -180,76 +182,7 @@ public class EntityReturn extends AbstractFetchOwner implements Return, FetchOwn
|
||||||
throw new AssertionFailure( "Could not locate resolved EntityKey");
|
throw new AssertionFailure( "Could not locate resolved EntityKey");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object existing = context.getSession().getEntityUsingInterceptor( entityKey );
|
return context.resolveEntityKey( entityKey, this );
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,7 +27,7 @@ package org.hibernate.loader.spi;
|
||||||
* The context for named parameters.
|
* The context for named parameters.
|
||||||
* <p/>
|
* <p/>
|
||||||
* NOTE : the hope with the SQL-redesign stuff is that this whole concept goes away, the idea being that
|
* 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
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
package org.hibernate.loader.spi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class ResultBuilder {
|
|
||||||
}
|
|
|
@ -23,10 +23,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.spi;
|
package org.hibernate.loader.spi;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
|
@ -34,9 +32,7 @@ import org.hibernate.engine.spi.QueryParameters;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.loader.EntityAliases;
|
import org.hibernate.loader.EntityAliases;
|
||||||
import org.hibernate.loader.plan.spi.EntityReference;
|
import org.hibernate.loader.plan.spi.EntityReference;
|
||||||
import org.hibernate.loader.plan.spi.Return;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.type.AssociationType;
|
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,8 +45,6 @@ public interface ResultSetProcessingContext {
|
||||||
|
|
||||||
public EntityKey getDictatedRootEntityKey();
|
public EntityKey getDictatedRootEntityKey();
|
||||||
|
|
||||||
public IdentifierResolutionContext getIdentifierResolutionContext(EntityReference entityReference);
|
|
||||||
|
|
||||||
public static interface IdentifierResolutionContext {
|
public static interface IdentifierResolutionContext {
|
||||||
public EntityReference getEntityReference();
|
public EntityReference getEntityReference();
|
||||||
|
|
||||||
|
@ -63,8 +57,21 @@ public interface ResultSetProcessingContext {
|
||||||
public EntityKey getEntityKey();
|
public EntityKey getEntityKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IdentifierResolutionContext getIdentifierResolutionContext(EntityReference entityReference);
|
||||||
|
|
||||||
public void registerHydratedEntity(EntityPersister persister, EntityKey entityKey, Object entityInstance);
|
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(
|
public void checkVersion(
|
||||||
ResultSet resultSet,
|
ResultSet resultSet,
|
||||||
EntityPersister persister,
|
EntityPersister persister,
|
||||||
|
|
Loading…
Reference in New Issue