implement @RowId

This commit is contained in:
Nathan Xu 2020-04-26 20:30:16 -04:00 committed by Steve Ebersole
parent 4c856725f8
commit fdc2112b19
17 changed files with 400 additions and 243 deletions

View File

@ -137,6 +137,8 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
EntityVersionMapping getVersionMapping(); EntityVersionMapping getVersionMapping();
EntityRowIdMapping getRowIdMapping();
default EntityDiscriminatorMapping getDiscriminatorMapping() { default EntityDiscriminatorMapping getDiscriminatorMapping() {
throw new NotYetImplementedFor6Exception( getClass() ); throw new NotYetImplementedFor6Exception( getClass() );
} }

View File

@ -0,0 +1,11 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.metamodel.mapping;
public interface EntityRowIdMapping extends VirtualModelPart {
String getRowIdName();
}

View File

@ -0,0 +1,119 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.metamodel.mapping.internal;
import java.util.function.BiConsumer;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.type.JavaObjectType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Nathan Xu
*/
public class EntityRowIdMappingImpl implements EntityRowIdMapping {
private final String rowIdName;
private final EntityMappingType declaringType;
private final String tableExpression;
public EntityRowIdMappingImpl(String rowIdName, String tableExpression, EntityMappingType declaringType) {
this.rowIdName = rowIdName;
this.tableExpression = tableExpression;
this.declaringType = declaringType;
}
@Override
public String getRowIdName() {
return rowIdName;
}
@Override
public MappingType getPartMappingType() {
return this::getJavaTypeDescriptor;
}
@Override
public JavaTypeDescriptor getJavaTypeDescriptor() {
return JavaObjectType.INSTANCE.getJavaTypeDescriptor();
}
@Override
public String getPartName() {
return rowIdName;
}
@Override
public NavigableRole getNavigableRole() {
return null;
}
@Override
public EntityMappingType findContainingEntityMapping() {
return declaringType;
}
@Override
public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference columnTableReference = tableGroup.resolveTableReference( tableExpression );
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( columnTableReference, rowIdName ),
sqlAstProcessingState -> new ColumnReference(
columnTableReference,
rowIdName,
JavaObjectType.INSTANCE,
sqlAstCreationState.getCreationContext().getSessionFactory()
)
),
JavaObjectType.INSTANCE.getJdbcMapping().getJavaTypeDescriptor(),
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
);
return new BasicResult<T>(
sqlSelection.getValuesArrayPosition(),
resultVariable,
getJavaTypeDescriptor(),
navigablePath
);
}
@Override
public void applySqlSelections(
NavigablePath navigablePath, TableGroup tableGroup, DomainResultCreationState creationState) {
}
@Override
public void applySqlSelections(
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState,
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
}
}

View File

@ -137,6 +137,7 @@ import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -146,6 +147,7 @@ import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping; import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
import org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl; import org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl;
import org.hibernate.metamodel.mapping.internal.EntityDiscriminatorMappingImpl; import org.hibernate.metamodel.mapping.internal.EntityDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.EntityRowIdMappingImpl;
import org.hibernate.metamodel.mapping.internal.EntityVersionMappingImpl; import org.hibernate.metamodel.mapping.internal.EntityVersionMappingImpl;
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType; import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper; import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
@ -198,7 +200,6 @@ import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.entity.internal.RootEntityResultImpl;
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl; import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
@ -1228,9 +1229,6 @@ public abstract class AbstractEntityPersister
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
//noinspection unchecked //noinspection unchecked
if ( navigablePath.getParent() == null && !creationState.forceIdentifierSelection()) {
return new RootEntityResultImpl( navigablePath, this, resultVariable, creationState );
}
return new EntityResultImpl( navigablePath, this, resultVariable, creationState ); return new EntityResultImpl( navigablePath, this, resultVariable, creationState );
} }
@ -5777,6 +5775,7 @@ public abstract class AbstractEntityPersister
private EntityIdentifierMapping identifierMapping; private EntityIdentifierMapping identifierMapping;
private NaturalIdMapping naturalIdMapping; private NaturalIdMapping naturalIdMapping;
private EntityVersionMapping versionMapping; private EntityVersionMapping versionMapping;
private EntityRowIdMapping rowIdMapping;
private EntityDiscriminatorMapping discriminatorMapping; private EntityDiscriminatorMapping discriminatorMapping;
private Map<String, AttributeMapping> declaredAttributeMappings = new LinkedHashMap<>(); private Map<String, AttributeMapping> declaredAttributeMappings = new LinkedHashMap<>();
@ -5807,6 +5806,7 @@ public abstract class AbstractEntityPersister
this.identifierMapping = superMappingType.getIdentifierMapping(); this.identifierMapping = superMappingType.getIdentifierMapping();
this.versionMapping = superMappingType.getVersionMapping(); this.versionMapping = superMappingType.getVersionMapping();
this.rowIdMapping = superMappingType.getRowIdMapping();
this.naturalIdMapping = superMappingType.getNaturalIdMapping(); this.naturalIdMapping = superMappingType.getNaturalIdMapping();
} }
else { else {
@ -5833,14 +5833,22 @@ public abstract class AbstractEntityPersister
); );
} }
if ( rowIdName == null ) {
rowIdMapping = null;
}
else {
rowIdMapping = creationProcess.processSubPart(
rowIdName,
(role, creationProcess1) -> new EntityRowIdMappingImpl( rowIdName, this.getRootTableName(), this)
);
}
buildDiscriminatorMapping(); buildDiscriminatorMapping();
// todo (6.0) : support for natural-id not yet implemented // todo (6.0) : support for natural-id not yet implemented
naturalIdMapping = null; naturalIdMapping = null;
} }
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel(); final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
int stateArrayPosition = getStateArrayInitialPosition( creationProcess ); int stateArrayPosition = getStateArrayInitialPosition( creationProcess );
@ -6219,6 +6227,11 @@ public abstract class AbstractEntityPersister
return versionMapping; return versionMapping;
} }
@Override
public EntityRowIdMapping getRowIdMapping() {
return rowIdMapping;
}
@Override @Override
public EntityDiscriminatorMapping getDiscriminatorMapping() { public EntityDiscriminatorMapping getDiscriminatorMapping() {
return discriminatorMapping; return discriminatorMapping;

View File

@ -54,6 +54,7 @@ import static org.hibernate.internal.log.LoggingHelper.toLoggableString;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
* @author Nathan Xu
*/ */
public abstract class AbstractEntityInitializer extends AbstractFetchParentAccess implements EntityInitializer { public abstract class AbstractEntityInitializer extends AbstractFetchParentAccess implements EntityInitializer {
@ -74,6 +75,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private final DomainResultAssembler identifierAssembler; private final DomainResultAssembler identifierAssembler;
private final DomainResultAssembler discriminatorAssembler; private final DomainResultAssembler discriminatorAssembler;
private final DomainResultAssembler versionAssembler; private final DomainResultAssembler versionAssembler;
private final DomainResultAssembler<Object> rowIdAssembler;
private final Map<AttributeMapping, DomainResultAssembler> assemblerMap; private final Map<AttributeMapping, DomainResultAssembler> assemblerMap;
@ -94,6 +96,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
DomainResult<?> identifierResult, DomainResult<?> identifierResult,
DomainResult<?> discriminatorResult, DomainResult<?> discriminatorResult,
DomainResult<?> versionResult, DomainResult<?> versionResult,
DomainResult<Object> rowIdResult,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
super( ); super( );
@ -164,6 +167,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
this.versionAssembler = null; this.versionAssembler = null;
} }
if ( rowIdResult != null ) {
this.rowIdAssembler = rowIdResult.createResultAssembler(
creationState
);
}
else {
this.rowIdAssembler = null;
}
assemblerMap = new IdentityHashMap<>( entityDescriptor.getNumberOfAttributeMappings() ); assemblerMap = new IdentityHashMap<>( entityDescriptor.getNumberOfAttributeMappings() );
entityDescriptor.visitFetchables( entityDescriptor.visitFetchables(
@ -506,23 +518,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
return; return;
} }
} }
final Object rowId = null;
// todo (6.0) : rowId
// final Object rowId;
// if ( concreteDescriptor.getHierarchy().getRowIdDescriptor() != null ) {
// rowId = ro sqlSelectionMappings.getRowIdSqlSelection().hydrateStateArray( rowProcessingState );
//
// if ( rowId == null ) {
// throw new HibernateException(
// "Could not read entity row-id from JDBC : " + entityKey
// );
// }
// }
// else {
// rowId = null;
// }
entityDescriptor.setIdentifier( entityInstance, entityIdentifier, session ); entityDescriptor.setIdentifier( entityInstance, entityIdentifier, session );
@ -547,6 +542,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
version = null; version = null;
} }
final Object rowId;
if ( rowIdAssembler != null ) {
rowId = rowIdAssembler.assemble( rowProcessingState );
}
else {
rowId = null;
}
final EntityEntry entityEntry = persistenceContext.addEntry( final EntityEntry entityEntry = persistenceContext.addEntry(
entityInstance, entityInstance,
Status.LOADING, Status.LOADING,

View File

@ -6,12 +6,19 @@
*/ */
package org.hibernate.sql.results.graph.entity; package org.hibernate.sql.results.graph.entity;
import java.util.ArrayList;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.AbstractFetchParent; import org.hibernate.sql.results.graph.AbstractFetchParent;
@ -29,6 +36,7 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
private final DomainResult identifierResult; private final DomainResult identifierResult;
private final DomainResult discriminatorResult; private final DomainResult discriminatorResult;
private final DomainResult versionResult; private final DomainResult versionResult;
private final DomainResult<Object> rowIdResult;
private final LockMode lockMode; private final LockMode lockMode;
private final EntityMappingType targetType; private final EntityMappingType targetType;
@ -57,12 +65,30 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
final TableGroup entityTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( navigablePath ); final TableGroup entityTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( navigablePath );
identifierResult = entityDescriptor.getIdentifierMapping().createDomainResult( final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup, if ( navigablePath.getParent() == null && !creationState.forceIdentifierSelection() ) {
null, identifierResult = null;
creationState if ( identifierMapping instanceof SingleAttributeIdentifierMapping ) {
); identifierMapping.createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
else {
visitCompositeIdentifierMapping( navigablePath, creationState, identifierMapping, entityTableGroup );
}
}
else {
identifierResult = entityDescriptor.getIdentifierMapping().createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
final EntityDiscriminatorMapping discriminatorMapping = getDiscriminatorMapping( entityDescriptor, entityTableGroup ); final EntityDiscriminatorMapping discriminatorMapping = getDiscriminatorMapping( entityDescriptor, entityTableGroup );
if ( discriminatorMapping != null ) { if ( discriminatorMapping != null ) {
@ -89,6 +115,48 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
creationState creationState
); );
} }
final EntityRowIdMapping rowIdMapping = entityDescriptor.getRowIdMapping();
if ( rowIdMapping == null ) {
rowIdResult = null;
}
else {
rowIdResult = rowIdMapping.createDomainResult(
navigablePath.append( rowIdMapping.getRowIdName() ),
entityTableGroup,
AbstractEntityPersister.ROWID_ALIAS,
creationState
);
}
}
private void visitCompositeIdentifierMapping(
NavigablePath navigablePath,
DomainResultCreationState creationState,
EntityIdentifierMapping identifierMapping,
TableGroup entityTableGroup) {
ManagedMappingType mappingType = (ManagedMappingType) identifierMapping.getPartMappingType();
fetches = new ArrayList<>();
mappingType.visitAttributeMappings(
attributeMapping -> {
if ( attributeMapping instanceof ToOneAttributeMapping ) {
( (ToOneAttributeMapping) attributeMapping ).getForeignKeyDescriptor().createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
else {
attributeMapping.createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
}
);
} }
protected EntityDiscriminatorMapping getDiscriminatorMapping( protected EntityDiscriminatorMapping getDiscriminatorMapping(
@ -127,4 +195,8 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
public DomainResult getVersionResult() { public DomainResult getVersionResult() {
return versionResult; return versionResult;
} }
public DomainResult<Object> getRowIdResult() {
return rowIdResult;
}
} }

View File

@ -35,6 +35,7 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
identifierResult, identifierResult,
discriminatorResult, discriminatorResult,
versionResult, versionResult,
null,
creationState creationState
); );
} }

View File

@ -77,6 +77,7 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode implements E
getIdentifierResult(), getIdentifierResult(),
getDiscriminatorResult(), getDiscriminatorResult(),
getVersionResult(), getVersionResult(),
getRowIdResult(),
creationState creationState
) )
); );

View File

@ -29,6 +29,7 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
DomainResult identifierResult, DomainResult identifierResult,
DomainResult discriminatorResult, DomainResult discriminatorResult,
DomainResult versionResult, DomainResult versionResult,
DomainResult<Object> rowIdResult,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
super( super(
resultDescriptor, resultDescriptor,
@ -37,6 +38,7 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
identifierResult, identifierResult,
discriminatorResult, discriminatorResult,
versionResult, versionResult,
rowIdResult,
creationState creationState
); );
} }

View File

@ -40,6 +40,7 @@ public class EntityResultJoinedSubclassImpl extends EntityResultImpl {
getIdentifierResult(), getIdentifierResult(),
getDiscriminatorResult(), getDiscriminatorResult(),
getVersionResult(), getVersionResult(),
getRowIdResult(),
creationState creationState
) )
); );

View File

@ -1,212 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.results.graph.entity.internal;
import java.util.ArrayList;
import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.AbstractFetchParent;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Andrea Boriero
*/
public class RootEntityResultImpl extends AbstractFetchParent implements EntityResultGraphNode, EntityResult {
private final String resultVariable;
private final EntityValuedModelPart referencedModelPart;
private final DomainResult discriminatorResult;
private final DomainResult versionResult;
private final LockMode lockMode;
public RootEntityResultImpl(
NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart,
String resultVariable,
DomainResultCreationState creationState) {
this( navigablePath, entityValuedModelPart, resultVariable, null, creationState );
}
@SuppressWarnings("WeakerAccess")
public RootEntityResultImpl(
NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart,
String resultVariable,
EntityMappingType targetType,
DomainResultCreationState creationState) {
super( entityValuedModelPart.getEntityMappingType(), navigablePath );
this.resultVariable = resultVariable;
this.referencedModelPart = entityValuedModelPart;
this.lockMode = creationState.getSqlAstCreationState().determineLockMode( resultVariable );
final EntityMappingType entityDescriptor = referencedModelPart.getEntityMappingType();
final TableGroup entityTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( navigablePath );
EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
if ( identifierMapping instanceof SingleAttributeIdentifierMapping ) {
identifierMapping.createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
else {
visitCompositeIdentifierMapping( navigablePath, creationState, identifierMapping, entityTableGroup );
}
final EntityDiscriminatorMapping discriminatorMapping = getDiscriminatorMapping( entityDescriptor, entityTableGroup );
if ( discriminatorMapping != null ) {
discriminatorResult = discriminatorMapping.createDomainResult(
navigablePath.append( EntityDiscriminatorMapping.ROLE_NAME ),
entityTableGroup,
null,
creationState
);
}
else {
discriminatorResult = null;
}
final EntityVersionMapping versionDescriptor = entityDescriptor.getVersionMapping();
if ( versionDescriptor == null ) {
versionResult = null;
}
else {
versionResult = versionDescriptor.createDomainResult(
navigablePath.append( versionDescriptor.getFetchableName() ),
entityTableGroup,
null,
creationState
);
}
afterInitialize( creationState );
}
private void visitCompositeIdentifierMapping(
NavigablePath navigablePath,
DomainResultCreationState creationState,
EntityIdentifierMapping identifierMapping,
TableGroup entityTableGroup) {
ManagedMappingType mappingType = (ManagedMappingType) identifierMapping.getPartMappingType();
fetches = new ArrayList<>();
mappingType.visitAttributeMappings(
attributeMapping -> {
if ( attributeMapping instanceof ToOneAttributeMapping ) {
((ToOneAttributeMapping)attributeMapping).getForeignKeyDescriptor().createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
else {
attributeMapping.createDomainResult(
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
entityTableGroup,
null,
creationState
);
}
}
);
}
protected EntityDiscriminatorMapping getDiscriminatorMapping(
EntityMappingType entityDescriptor,
TableGroup entityTableGroup) {
return entityDescriptor.getDiscriminatorMapping();
}
@Override
public EntityMappingType getReferencedMappingContainer() {
return getEntityValuedModelPart().getEntityMappingType();
}
@Override
public EntityValuedModelPart getEntityValuedModelPart() {
return referencedModelPart;
}
@Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
return getEntityValuedModelPart().getEntityMappingType().getMappedJavaTypeDescriptor();
}
public LockMode getLockMode() {
return lockMode;
}
public DomainResult getDiscriminatorResult() {
return discriminatorResult;
}
public DomainResult getVersionResult() {
return versionResult;
}
@Override
public FetchableContainer getReferencedMappingType() {
return getReferencedMappingContainer();
}
@Override
public EntityValuedModelPart getReferencedModePart() {
return getEntityValuedModelPart();
}
@Override
public String getResultVariable() {
return resultVariable;
}
@Override
public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) {
// todo (6.0) : seems like here is where we ought to determine the SQL selection mappings
final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(),
() -> new EntityResultInitializer(
this,
getNavigablePath(),
getLockMode(),
null,
getDiscriminatorResult(),
getVersionResult(),
creationState
)
);
return new EntityAssembler( getResultJavaTypeDescriptor(), initializer );
}
@Override
public String toString() {
return "EntityResultImpl {" + getNavigablePath() + "}";
}
}

View File

@ -45,6 +45,7 @@ import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
@ -693,6 +694,11 @@ public class PersisterClassProviderTest {
return null; return null;
} }
@Override
public EntityRowIdMapping getRowIdMapping() {
return null;
}
@Override @Override
public NaturalIdMapping getNaturalIdMapping() { public NaturalIdMapping getNaturalIdMapping() {
return null; return null;

View File

@ -0,0 +1,122 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.rowid;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.RowId;
import org.hibernate.dialect.Oracle9iDialect;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
import static org.junit.Assert.assertThat;
/**
* @author Nathan Xu
*/
@DomainModel( annotatedClasses = RowIdTest.Product.class )
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@RequiresDialect( value = Oracle9iDialect.class )
public class RowIdTest {
@BeforeEach
void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
Product product = new Product();
product.setId( 1L );
product.setName( "Mobile phone" );
product.setNumber( "123-456-7890" );
session.persist( product );
} );
}
@Test
void testRowId(SessionFactoryScope scope) {
final String updatedName = "Smart phone";
scope.inTransaction( session -> {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
Product product = session.find( Product.class, 1L );
List<String> sqls = statementInspector.getSqlQueries();
assertThat( sqls, hasSize( 1 ) );
assertThat( sqls.get(0).matches( "(?i).*\\bselect\\b.+\\.ROWID.*\\bfrom\\s+product\\b.*" ), is( true ) );
assertThat( product.getName(), not( is( updatedName ) ) );
product.setName( updatedName );
statementInspector.clear();
session.flush();
sqls = statementInspector.getSqlQueries();
assertThat( sqls, hasSize( 1 ) );
assertThat( sqls.get( 0 ).matches( "(?i).*\\bupdate\\s+product\\b.+?\\bwhere\\s+ROWID\\s*=.*" ), is( true ) );
} );
scope.inTransaction( session -> {
Product product = session.createQuery( "from Product", Product.class ).uniqueResult();
assertThat( product.getName(), is( updatedName ) );
} );
}
@Entity(name = "Product")
@Table(name = "product")
@RowId("ROWID")
public static class Product {
@Id
private Long id;
@Column(name = "`name`")
private String name;
@Column(name = "`number`")
private String number;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
}

View File

@ -45,6 +45,7 @@ import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
@ -631,6 +632,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
return null; return null;
} }
@Override
public EntityRowIdMapping getRowIdMapping() {
return null;
}
@Override @Override
public NaturalIdMapping getNaturalIdMapping() { public NaturalIdMapping getNaturalIdMapping() {
return null; return null;

View File

@ -49,6 +49,7 @@ import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
@ -742,6 +743,11 @@ public class CustomPersister implements EntityPersister {
return null; return null;
} }
@Override
public EntityRowIdMapping getRowIdMapping() {
return null;
}
@Override @Override
public NaturalIdMapping getNaturalIdMapping() { public NaturalIdMapping getNaturalIdMapping() {
return null; return null;

View File

@ -7,6 +7,7 @@
package org.hibernate.testing.jdbc; package org.hibernate.testing.jdbc;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import org.hibernate.resource.jdbc.spi.StatementInspector; import org.hibernate.resource.jdbc.spi.StatementInspector;
@ -19,7 +20,7 @@ import static org.junit.Assert.assertTrue;
* @author Andrea Boriero * @author Andrea Boriero
*/ */
public class SQLStatementInspector implements StatementInspector { public class SQLStatementInspector implements StatementInspector {
private final LinkedList<String> sqlQueries = new LinkedList<>(); private final List<String> sqlQueries = new LinkedList<>();
public SQLStatementInspector() { public SQLStatementInspector() {
} }
@ -30,7 +31,7 @@ public class SQLStatementInspector implements StatementInspector {
return sql; return sql;
} }
public LinkedList<String> getSqlQueries() { public List<String> getSqlQueries() {
return sqlQueries; return sqlQueries;
} }

View File

@ -18,7 +18,9 @@ import static org.junit.Assert.assertTrue;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
* @deprecated use {@link SQLStatementInspector} instead
*/ */
@Deprecated
public class SQLStatementInterceptor { public class SQLStatementInterceptor {
private final LinkedList<String> sqlQueries = new LinkedList<>(); private final LinkedList<String> sqlQueries = new LinkedList<>();