implement @RowId
This commit is contained in:
parent
4c856725f8
commit
fdc2112b19
|
@ -137,6 +137,8 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
|
|||
|
||||
EntityVersionMapping getVersionMapping();
|
||||
|
||||
EntityRowIdMapping getRowIdMapping();
|
||||
|
||||
default EntityDiscriminatorMapping getDiscriminatorMapping() {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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) {
|
||||
}
|
||||
|
||||
}
|
|
@ -137,6 +137,7 @@ import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
|
|||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
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.internal.BasicEntityIdentifierMappingImpl;
|
||||
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.InFlightEntityMappingType;
|
||||
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.Fetchable;
|
||||
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.stat.spi.StatisticsImplementor;
|
||||
import org.hibernate.tuple.GenerationTiming;
|
||||
|
@ -1228,9 +1229,6 @@ public abstract class AbstractEntityPersister
|
|||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
//noinspection unchecked
|
||||
if ( navigablePath.getParent() == null && !creationState.forceIdentifierSelection()) {
|
||||
return new RootEntityResultImpl( navigablePath, this, resultVariable, creationState );
|
||||
}
|
||||
return new EntityResultImpl( navigablePath, this, resultVariable, creationState );
|
||||
}
|
||||
|
||||
|
@ -5777,6 +5775,7 @@ public abstract class AbstractEntityPersister
|
|||
private EntityIdentifierMapping identifierMapping;
|
||||
private NaturalIdMapping naturalIdMapping;
|
||||
private EntityVersionMapping versionMapping;
|
||||
private EntityRowIdMapping rowIdMapping;
|
||||
private EntityDiscriminatorMapping discriminatorMapping;
|
||||
|
||||
private Map<String, AttributeMapping> declaredAttributeMappings = new LinkedHashMap<>();
|
||||
|
@ -5807,6 +5806,7 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
this.identifierMapping = superMappingType.getIdentifierMapping();
|
||||
this.versionMapping = superMappingType.getVersionMapping();
|
||||
this.rowIdMapping = superMappingType.getRowIdMapping();
|
||||
this.naturalIdMapping = superMappingType.getNaturalIdMapping();
|
||||
}
|
||||
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();
|
||||
|
||||
// todo (6.0) : support for natural-id not yet implemented
|
||||
naturalIdMapping = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
|
||||
int stateArrayPosition = getStateArrayInitialPosition( creationProcess );
|
||||
|
||||
|
@ -6219,6 +6227,11 @@ public abstract class AbstractEntityPersister
|
|||
return versionMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRowIdMapping getRowIdMapping() {
|
||||
return rowIdMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDiscriminatorMapping getDiscriminatorMapping() {
|
||||
return discriminatorMapping;
|
||||
|
|
|
@ -54,6 +54,7 @@ import static org.hibernate.internal.log.LoggingHelper.toLoggableString;
|
|||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
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 discriminatorAssembler;
|
||||
private final DomainResultAssembler versionAssembler;
|
||||
private final DomainResultAssembler<Object> rowIdAssembler;
|
||||
|
||||
private final Map<AttributeMapping, DomainResultAssembler> assemblerMap;
|
||||
|
||||
|
@ -94,6 +96,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
DomainResult<?> identifierResult,
|
||||
DomainResult<?> discriminatorResult,
|
||||
DomainResult<?> versionResult,
|
||||
DomainResult<Object> rowIdResult,
|
||||
AssemblerCreationState creationState) {
|
||||
super( );
|
||||
|
||||
|
@ -164,6 +167,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
this.versionAssembler = null;
|
||||
}
|
||||
|
||||
if ( rowIdResult != null ) {
|
||||
this.rowIdAssembler = rowIdResult.createResultAssembler(
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
this.rowIdAssembler = null;
|
||||
}
|
||||
|
||||
assemblerMap = new IdentityHashMap<>( entityDescriptor.getNumberOfAttributeMappings() );
|
||||
|
||||
entityDescriptor.visitFetchables(
|
||||
|
@ -506,23 +518,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
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 );
|
||||
|
||||
|
@ -547,6 +542,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
version = null;
|
||||
}
|
||||
|
||||
final Object rowId;
|
||||
|
||||
if ( rowIdAssembler != null ) {
|
||||
rowId = rowIdAssembler.assemble( rowProcessingState );
|
||||
}
|
||||
else {
|
||||
rowId = null;
|
||||
}
|
||||
|
||||
final EntityEntry entityEntry = persistenceContext.addEntry(
|
||||
entityInstance,
|
||||
Status.LOADING,
|
||||
|
|
|
@ -6,12 +6,19 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph.entity;
|
||||
|
||||
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.EntityRowIdMapping;
|
||||
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.persister.entity.AbstractEntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.graph.AbstractFetchParent;
|
||||
|
@ -29,6 +36,7 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
|
|||
private final DomainResult identifierResult;
|
||||
private final DomainResult discriminatorResult;
|
||||
private final DomainResult versionResult;
|
||||
private final DomainResult<Object> rowIdResult;
|
||||
private final LockMode lockMode;
|
||||
|
||||
private final EntityMappingType targetType;
|
||||
|
@ -57,12 +65,30 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
|
|||
|
||||
final TableGroup entityTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( navigablePath );
|
||||
|
||||
identifierResult = entityDescriptor.getIdentifierMapping().createDomainResult(
|
||||
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
|
||||
entityTableGroup,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
|
||||
if ( navigablePath.getParent() == null && !creationState.forceIdentifierSelection() ) {
|
||||
identifierResult = null;
|
||||
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 );
|
||||
if ( discriminatorMapping != null ) {
|
||||
|
@ -89,6 +115,48 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
|
|||
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(
|
||||
|
@ -127,4 +195,8 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
|
|||
public DomainResult getVersionResult() {
|
||||
return versionResult;
|
||||
}
|
||||
|
||||
public DomainResult<Object> getRowIdResult() {
|
||||
return rowIdResult;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
|
|||
identifierResult,
|
||||
discriminatorResult,
|
||||
versionResult,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode implements E
|
|||
getIdentifierResult(),
|
||||
getDiscriminatorResult(),
|
||||
getVersionResult(),
|
||||
getRowIdResult(),
|
||||
creationState
|
||||
)
|
||||
);
|
||||
|
|
|
@ -29,6 +29,7 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
|
|||
DomainResult identifierResult,
|
||||
DomainResult discriminatorResult,
|
||||
DomainResult versionResult,
|
||||
DomainResult<Object> rowIdResult,
|
||||
AssemblerCreationState creationState) {
|
||||
super(
|
||||
resultDescriptor,
|
||||
|
@ -37,6 +38,7 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
|
|||
identifierResult,
|
||||
discriminatorResult,
|
||||
versionResult,
|
||||
rowIdResult,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public class EntityResultJoinedSubclassImpl extends EntityResultImpl {
|
|||
getIdentifierResult(),
|
||||
getDiscriminatorResult(),
|
||||
getVersionResult(),
|
||||
getRowIdResult(),
|
||||
creationState
|
||||
)
|
||||
);
|
||||
|
|
|
@ -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() + "}";
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@ import org.hibernate.metadata.ClassMetadata;
|
|||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
|
@ -693,6 +694,11 @@ public class PersisterClassProviderTest {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRowIdMapping getRowIdMapping() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdMapping getNaturalIdMapping() {
|
||||
return null;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@ import org.hibernate.metadata.CollectionMetadata;
|
|||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
|
@ -631,6 +632,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRowIdMapping getRowIdMapping() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdMapping getNaturalIdMapping() {
|
||||
return null;
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.hibernate.metadata.ClassMetadata;
|
|||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
|
@ -742,6 +743,11 @@ public class CustomPersister implements EntityPersister {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRowIdMapping getRowIdMapping() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdMapping getNaturalIdMapping() {
|
||||
return null;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.testing.jdbc;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
|
||||
|
@ -19,7 +20,7 @@ import static org.junit.Assert.assertTrue;
|
|||
* @author Andrea Boriero
|
||||
*/
|
||||
public class SQLStatementInspector implements StatementInspector {
|
||||
private final LinkedList<String> sqlQueries = new LinkedList<>();
|
||||
private final List<String> sqlQueries = new LinkedList<>();
|
||||
|
||||
public SQLStatementInspector() {
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ public class SQLStatementInspector implements StatementInspector {
|
|||
return sql;
|
||||
}
|
||||
|
||||
public LinkedList<String> getSqlQueries() {
|
||||
public List<String> getSqlQueries() {
|
||||
return sqlQueries;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
* @deprecated use {@link SQLStatementInspector} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class SQLStatementInterceptor {
|
||||
|
||||
private final LinkedList<String> sqlQueries = new LinkedList<>();
|
||||
|
|
Loading…
Reference in New Issue