HHH-15899 Add @PartitionColumn annotation

This commit is contained in:
Christian Beikov 2022-12-20 22:45:58 +01:00
parent fb840ef84f
commit 50db219047
46 changed files with 494 additions and 7 deletions

View File

@ -0,0 +1,25 @@
/*
* 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.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Identifies a field of an entity that holds the partition key of a table.
*
* @since 6.2
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface PartitionKey {
}

View File

@ -28,6 +28,7 @@ import org.hibernate.annotations.CollectionIdJavaType;
import org.hibernate.annotations.CollectionIdJdbcType; import org.hibernate.annotations.CollectionIdJdbcType;
import org.hibernate.annotations.CollectionIdJdbcTypeCode; import org.hibernate.annotations.CollectionIdJdbcTypeCode;
import org.hibernate.annotations.CollectionIdMutability; import org.hibernate.annotations.CollectionIdMutability;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.annotations.CollectionIdType; import org.hibernate.annotations.CollectionIdType;
import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.annotations.JdbcTypeCode;
@ -148,6 +149,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
private EnumType enumType; private EnumType enumType;
private TemporalType temporalPrecision; private TemporalType temporalPrecision;
private TimeZoneStorageType timeZoneStorageType; private TimeZoneStorageType timeZoneStorageType;
private boolean partitionKey;
private Table table; private Table table;
private AnnotatedColumns columns; private AnnotatedColumns columns;
@ -983,6 +985,10 @@ public class BasicValueBinder implements JdbcTypeIndicators {
} }
} }
} }
final PartitionKey partitionKey = attributeXProperty.getAnnotation( PartitionKey.class );
if ( partitionKey != null ) {
this.partitionKey = true;
}
} }
private static Class<? extends UserType<?>> normalizeUserType(Class<? extends UserType<?>> userType) { private static Class<? extends UserType<?>> normalizeUserType(Class<? extends UserType<?>> userType) {
@ -1103,6 +1109,8 @@ public class BasicValueBinder implements JdbcTypeIndicators {
basicValue.setTimeZoneStorageType( timeZoneStorageType ); basicValue.setTimeZoneStorageType( timeZoneStorageType );
} }
basicValue.setPartitionKey( partitionKey );
if ( temporalPrecision != null ) { if ( temporalPrecision != null ) {
basicValue.setTemporalPrecision( temporalPrecision ); basicValue.setTemporalPrecision( temporalPrecision );
} }

View File

@ -1115,6 +1115,19 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
this.hasSubselectLoadableCollections = hasSubselectCollections; this.hasSubselectLoadableCollections = hasSubselectCollections;
} }
public boolean hasPartitionedSelectionMapping() {
if ( getSuperclass() != null && getSuperclass().hasPartitionedSelectionMapping() ) {
return true;
}
for ( Property property : getProperties() ) {
final Value value = property.getValue();
if ( value instanceof BasicValue && ( (BasicValue) value ).isPartitionKey() ) {
return true;
}
}
return false;
}
public Component getIdentifierMapper() { public Component getIdentifierMapper() {
return identifierMapper; return identifierMapper;
} }

View File

@ -80,6 +80,7 @@ public abstract class SimpleValue implements KeyValue {
private final List<Selectable> columns = new ArrayList<>(); private final List<Selectable> columns = new ArrayList<>();
private final List<Boolean> insertability = new ArrayList<>(); private final List<Boolean> insertability = new ArrayList<>();
private final List<Boolean> updatability = new ArrayList<>(); private final List<Boolean> updatability = new ArrayList<>();
private boolean partitionKey;
private String typeName; private String typeName;
private Properties typeParameters; private Properties typeParameters;
@ -120,6 +121,7 @@ public abstract class SimpleValue implements KeyValue {
this.columns.addAll( original.columns ); this.columns.addAll( original.columns );
this.insertability.addAll( original.insertability ); this.insertability.addAll( original.insertability );
this.updatability.addAll( original.updatability ); this.updatability.addAll( original.updatability );
this.partitionKey = original.partitionKey;
this.typeName = original.typeName; this.typeName = original.typeName;
this.typeParameters = original.typeParameters == null ? null : new Properties( original.typeParameters ); this.typeParameters = original.typeParameters == null ? null : new Properties( original.typeParameters );
this.isVersion = original.isVersion; this.isVersion = original.isVersion;
@ -866,6 +868,14 @@ public abstract class SimpleValue implements KeyValue {
return false; return false;
} }
public boolean isPartitionKey() {
return partitionKey;
}
public void setPartitionKey(boolean partitionColumn) {
this.partitionKey = partitionColumn;
}
private static boolean[] extractBooleansFromList(List<Boolean> list) { private static boolean[] extractBooleansFromList(List<Boolean> list) {
final boolean[] array = new boolean[ list.size() ]; final boolean[] array = new boolean[ list.size() ];
int i = 0; int i = 0;

View File

@ -288,4 +288,9 @@ public abstract class AbstractCompositeIdentifierMapping
return entityMapping; return entityMapping;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
} }

View File

@ -51,4 +51,9 @@ public interface BasicValuedModelPart extends BasicValuedMapping, ValuedModelPar
consumer.accept( 0, this ); consumer.accept( 0, this );
return getJdbcTypeCount(); return getJdbcTypeCount();
} }
@Override
default boolean hasPartitionedSelectionMapping() {
return isPartitioned();
}
} }

View File

@ -101,4 +101,14 @@ public interface ManagedMappingType extends MappingType, FetchableContainer {
} }
return false; return false;
} }
@Override
default boolean hasPartitionedSelectionMapping() {
for ( AttributeMapping attributeMapping : getAttributeMappings() ) {
if ( attributeMapping.hasPartitionedSelectionMapping() ) {
return true;
}
}
return false;
}
} }

View File

@ -91,6 +91,8 @@ public interface ModelPart extends MappingModelExpressible {
return false; return false;
} }
boolean hasPartitionedSelectionMapping();
/** /**
* Create a DomainResult for a specific reference to this ModelPart. * Create a DomainResult for a specific reference to this ModelPart.
*/ */

View File

@ -104,6 +104,11 @@ public interface SelectableConsumer {
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override @Override
public String getColumnDefinition() { public String getColumnDefinition() {
// we could probably use the details from `base`, but // we could probably use the details from `base`, but
@ -217,6 +222,11 @@ public interface SelectableConsumer {
return true; return true;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override @Override
public JdbcMapping getJdbcMapping() { public JdbcMapping getJdbcMapping() {
return null; return null;

View File

@ -65,4 +65,6 @@ public interface SelectableMapping extends SqlTypedMapping {
boolean isInsertable(); boolean isInsertable();
boolean isUpdateable(); boolean isUpdateable();
boolean isPartitioned();
} }

View File

@ -61,6 +61,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
private final boolean insertable; private final boolean insertable;
private final boolean updateable; private final boolean updateable;
private final boolean partitioned;
private final MetaType metaType; private final MetaType metaType;
public AnyDiscriminatorPart( public AnyDiscriminatorPart(
@ -74,6 +75,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
Integer scale, Integer scale,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
MetaType metaType) { MetaType metaType) {
this.navigableRole = partRole; this.navigableRole = partRole;
this.declaringType = declaringType; this.declaringType = declaringType;
@ -85,6 +87,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
this.scale = scale; this.scale = scale;
this.insertable = insertable; this.insertable = insertable;
this.updateable = updateable; this.updateable = updateable;
this.partitioned = partitioned;
this.metaType = metaType; this.metaType = metaType;
} }
@ -126,6 +129,11 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
return updateable; return updateable;
} }
@Override
public boolean isPartitioned() {
return partitioned;
}
@Override @Override
public String getCustomReadExpression() { public String getCustomReadExpression() {
return null; return null;

View File

@ -56,6 +56,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
private final boolean nullable; private final boolean nullable;
private final boolean insertable; private final boolean insertable;
private final boolean updateable; private final boolean updateable;
private final boolean partitioned;
private final JdbcMapping jdbcMapping; private final JdbcMapping jdbcMapping;
public AnyKeyPart( public AnyKeyPart(
@ -70,6 +71,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
boolean nullable, boolean nullable,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
JdbcMapping jdbcMapping) { JdbcMapping jdbcMapping) {
this.navigableRole = navigableRole; this.navigableRole = navigableRole;
this.table = table; this.table = table;
@ -82,6 +84,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
this.nullable = nullable; this.nullable = nullable;
this.insertable = insertable; this.insertable = insertable;
this.updateable = updateable; this.updateable = updateable;
this.partitioned = partitioned;
this.jdbcMapping = jdbcMapping; this.jdbcMapping = jdbcMapping;
} }
@ -115,6 +118,11 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
return updateable; return updateable;
} }
@Override
public boolean isPartitioned() {
return partitioned;
}
@Override @Override
public String getCustomReadExpression() { public String getCustomReadExpression() {
return null; return null;

View File

@ -63,6 +63,7 @@ public class BasicAttributeMapping
private final boolean nullable; private final boolean nullable;
private final boolean insertable; private final boolean insertable;
private final boolean updateable; private final boolean updateable;
private final boolean partitioned;
private final JavaType domainTypeDescriptor; private final JavaType domainTypeDescriptor;
@ -87,6 +88,7 @@ public class BasicAttributeMapping
boolean nullable, boolean nullable,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
JdbcMapping jdbcMapping, JdbcMapping jdbcMapping,
ManagedMappingType declaringType, ManagedMappingType declaringType,
PropertyAccess propertyAccess) { PropertyAccess propertyAccess) {
@ -117,6 +119,7 @@ public class BasicAttributeMapping
this.nullable = nullable; this.nullable = nullable;
this.insertable = insertable; this.insertable = insertable;
this.updateable = updateable; this.updateable = updateable;
this.partitioned = partitioned;
this.jdbcMapping = jdbcMapping; this.jdbcMapping = jdbcMapping;
this.domainTypeDescriptor = jdbcMapping.getJavaTypeDescriptor(); this.domainTypeDescriptor = jdbcMapping.getJavaTypeDescriptor();
@ -175,6 +178,7 @@ public class BasicAttributeMapping
selectableMapping.isNullable(), selectableMapping.isNullable(),
insertable, insertable,
updateable, updateable,
selectableMapping.isPartitioned(),
original.getJdbcMapping(), original.getJdbcMapping(),
declaringType, declaringType,
propertyAccess propertyAccess
@ -231,6 +235,11 @@ public class BasicAttributeMapping
return updateable; return updateable;
} }
@Override
public boolean isPartitioned() {
return partitioned;
}
@Override @Override
public String getCustomReadExpression() { public String getCustomReadExpression() {
return customReadExpression; return customReadExpression;

View File

@ -314,6 +314,16 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
return insertable; return insertable;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public String getCustomReadExpression() { public String getCustomReadExpression() {
return null; return null;

View File

@ -98,6 +98,11 @@ public class BasicValuedCollectionPart
return selectableMapping.isInsertable(); return selectableMapping.isInsertable();
} }
@Override
public boolean isPartitioned() {
return selectableMapping.isPartitioned();
}
@Override @Override
public boolean isUpdateable() { public boolean isUpdateable() {
return selectableMapping.isUpdateable(); return selectableMapping.isUpdateable();

View File

@ -220,6 +220,16 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public String getContainingTableExpression() { public String getContainingTableExpression() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@ -89,6 +89,16 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public boolean isNullable() { public boolean isNullable() {
return false; return false;

View File

@ -24,6 +24,7 @@ import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
import org.hibernate.loader.ast.spi.NaturalIdLoader; import org.hibernate.loader.ast.spi.NaturalIdLoader;
import org.hibernate.mapping.IndexedConsumer; import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.UnsupportedMappingException;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.AttributeMetadata; import org.hibernate.metamodel.mapping.AttributeMetadata;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
@ -265,6 +266,16 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
return getJavaType(); return getJavaType();
} }
@Override
public boolean hasPartitionedSelectionMapping() {
for ( AttributeMapping attributeMapping : attributes ) {
if ( attributeMapping.hasPartitionedSelectionMapping() ) {
return true;
}
}
return false;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ModelPart // ModelPart

View File

@ -357,6 +357,12 @@ public class DiscriminatedAssociationAttributeMapping
consumer.accept( getKeyPart() ); consumer.accept( getKeyPart() );
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return discriminatorMapping.getDiscriminatorPart().isPartitioned()
|| discriminatorMapping.getKeyPart().isPartitioned();
}
public static class MutabilityPlanImpl implements MutabilityPlan<Object> { public static class MutabilityPlanImpl implements MutabilityPlan<Object> {
// for now use the AnyType for consistency with write-operations // for now use the AnyType for consistency with write-operations
private final AnyType anyType; private final AnyType anyType;

View File

@ -6,11 +6,8 @@
*/ */
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -98,6 +95,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
metaColumn.getScale(), metaColumn.getScale(),
bootValueMapping.isColumnInsertable( 0 ), bootValueMapping.isColumnInsertable( 0 ),
bootValueMapping.isColumnUpdateable( 0 ), bootValueMapping.isColumnUpdateable( 0 ),
bootValueMapping.isPartitionKey(),
(MetaType) anyType.getDiscriminatorType() (MetaType) anyType.getDiscriminatorType()
); );
@ -115,6 +113,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
bootValueMapping.isNullable(), bootValueMapping.isNullable(),
bootValueMapping.isColumnInsertable( 1 ), bootValueMapping.isColumnInsertable( 1 ),
bootValueMapping.isColumnUpdateable( 1 ), bootValueMapping.isColumnUpdateable( 1 ),
bootValueMapping.isPartitionKey(),
keyType keyType
); );

View File

@ -127,6 +127,12 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
return discriminatorMapping; return discriminatorMapping;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return discriminatorMapping.getDiscriminatorPart().isPartitioned()
|| discriminatorMapping.getKeyPart().isPartitioned();
}
@Override @Override
public String toString() { public String toString() {
return "DiscriminatedCollectionPart(" + getNavigableRole() + ")@" + System.identityHashCode( this ); return "DiscriminatedCollectionPart(" + getNavigableRole() + ")@" + System.identityHashCode( this );

View File

@ -203,6 +203,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
creationContext.getTypeConfiguration(), creationContext.getTypeConfiguration(),
insertable, insertable,
updatable, updatable,
false,
dialect, dialect,
null null
); );

View File

@ -214,6 +214,11 @@ public class EmbeddedAttributeMapping
getEmbeddableTypeDescriptor().decompose( domainValue, valueConsumer, session ); getEmbeddableTypeDescriptor().decompose( domainValue, valueConsumer, session );
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return getEmbeddableTypeDescriptor().hasPartitionedSelectionMapping();
}
@Override @Override
public <T> DomainResult<T> createDomainResult( public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath, NavigablePath navigablePath,

View File

@ -355,4 +355,9 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
return FetchTiming.IMMEDIATE; return FetchTiming.IMMEDIATE;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return getEmbeddableTypeDescriptor().hasPartitionedSelectionMapping();
}
} }

View File

@ -598,4 +598,9 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
public Object disassemble(Object value, SharedSessionContractImplementor session) { public Object disassemble(Object value, SharedSessionContractImplementor session) {
return targetSide.getModelPart().disassemble( value, session ); return targetSide.getModelPart().disassemble( value, session );
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return keySide.getModelPart().hasPartitionedSelectionMapping();
}
} }

View File

@ -76,6 +76,11 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping {
return declaringType; return declaringType;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public <T> DomainResult<T> createDomainResult( public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath, NavigablePath navigablePath,
@ -205,6 +210,11 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping {
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override @Override
public JdbcMapping getJdbcMapping() { public JdbcMapping getJdbcMapping() {
return rowIdType.getJdbcMapping(); return rowIdType.getJdbcMapping();

View File

@ -137,6 +137,16 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
return true; return true;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public String getCustomReadExpression() { public String getCustomReadExpression() {
return null; return null;

View File

@ -132,6 +132,16 @@ public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminato
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public boolean hasPhysicalColumn() { public boolean hasPhysicalColumn() {
return isPhysical; return isPhysical;

View File

@ -255,6 +255,7 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
return join; return join;
} }
@Override
public LazyTableGroup createRootTableGroupJoin( public LazyTableGroup createRootTableGroupJoin(
NavigablePath navigablePath, NavigablePath navigablePath,
TableGroup lhs, TableGroup lhs,
@ -329,6 +330,11 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
return lazyTableGroup; return lazyTableGroup;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return foreignKey.hasPartitionedSelectionMapping();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialization // Initialization
@ -464,6 +470,7 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
true, true,
false, false,
false,
creationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect(), creationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect(),
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -630,6 +637,7 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
columnInsertable, columnInsertable,
columnUpdateable, columnUpdateable,
((SimpleValue) fkBootDescriptorSource).isPartitionKey(),
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );

View File

@ -17,7 +17,6 @@ import org.hibernate.FetchMode;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.SharedSessionContract; import org.hibernate.SharedSessionContract;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.collection.internal.StandardArraySemantics; import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.internal.StandardBagSemantics; import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics; import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
@ -197,7 +196,7 @@ public class MappingModelCreationHelper {
PropertyAccess propertyAccess, PropertyAccess propertyAccess,
CascadeStyle cascadeStyle, CascadeStyle cascadeStyle,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
final Value value = bootProperty.getValue(); final SimpleValue value = (SimpleValue) bootProperty.getValue();
final BasicValue.Resolution<?> resolution = ( (Resolvable) value ).resolve(); final BasicValue.Resolution<?> resolution = ( (Resolvable) value ).resolve();
SimpleAttributeMetadata attributeMetadata = new SimpleAttributeMetadata( propertyAccess, resolution.getMutabilityPlan(), bootProperty, value ); SimpleAttributeMetadata attributeMetadata = new SimpleAttributeMetadata( propertyAccess, resolution.getMutabilityPlan(), bootProperty, value );
@ -240,6 +239,7 @@ public class MappingModelCreationHelper {
nullable, nullable,
insertable, insertable,
updateable, updateable,
value.isPartitionKey(),
attrType, attrType,
declaringType, declaringType,
propertyAccess propertyAccess
@ -430,6 +430,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
index.isColumnInsertable( 0 ), index.isColumnInsertable( 0 ),
index.isColumnUpdateable( 0 ), index.isColumnUpdateable( 0 ),
false,
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -482,6 +483,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
index.isColumnInsertable( 0 ), index.isColumnInsertable( 0 ),
index.isColumnUpdateable( 0 ), index.isColumnUpdateable( 0 ),
false,
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -685,6 +687,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
bootValueMappingKey.isColumnInsertable( 0 ), bootValueMappingKey.isColumnInsertable( 0 ),
bootValueMappingKey.isColumnUpdateable( 0 ), bootValueMappingKey.isColumnUpdateable( 0 ),
false,
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -859,6 +862,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
value.isColumnInsertable( i ), value.isColumnInsertable( i ),
value.isColumnUpdateable( i ), value.isColumnUpdateable( i ),
((SimpleValue) value).isPartitionKey(),
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -873,6 +877,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
value.isColumnInsertable( 0 ), value.isColumnInsertable( 0 ),
value.isColumnUpdateable( 0 ), value.isColumnUpdateable( 0 ),
((SimpleValue) value).isPartitionKey(),
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -1181,6 +1186,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
insertable, insertable,
updatable, updatable,
false,
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );
@ -1280,6 +1286,7 @@ public class MappingModelCreationHelper {
creationProcess.getCreationContext().getTypeConfiguration(), creationProcess.getCreationContext().getTypeConfiguration(),
basicElement.isColumnInsertable( 0 ), basicElement.isColumnInsertable( 0 ),
basicElement.isColumnUpdateable( 0 ), basicElement.isColumnUpdateable( 0 ),
basicElement.isPartitionKey(),
dialect, dialect,
creationProcess.getSqmFunctionRegistry() creationProcess.getSqmFunctionRegistry()
); );

View File

@ -123,6 +123,11 @@ public class OneToManyCollectionPart extends AbstractEntityCollectionPart implem
return fetchAssociationKey; return fetchAssociationKey;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// TableGroupJoinProducer // TableGroupJoinProducer

View File

@ -361,6 +361,11 @@ public class PluralAttributeMappingImpl
return fetchTiming; return fetchTiming;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public <T> DomainResult<T> createDomainResult( public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath, NavigablePath navigablePath,
@ -662,6 +667,7 @@ public class PluralAttributeMappingImpl
return tableGroup; return tableGroup;
} }
@Override
public void setForeignKeyDescriptor(ForeignKeyDescriptor fkDescriptor) { public void setForeignKeyDescriptor(ForeignKeyDescriptor fkDescriptor) {
this.fkDescriptor = fkDescriptor; this.fkDescriptor = fkDescriptor;
} }

View File

@ -31,6 +31,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
private final boolean nullable; private final boolean nullable;
private final boolean insertable; private final boolean insertable;
private final boolean updateable; private final boolean updateable;
private final boolean partitioned;
private final boolean isFormula; private final boolean isFormula;
public SelectableMappingImpl( public SelectableMappingImpl(
@ -46,6 +47,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
boolean nullable, boolean nullable,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
boolean isFormula, boolean isFormula,
JdbcMapping jdbcMapping) { JdbcMapping jdbcMapping) {
super( columnDefinition, length, precision, scale, jdbcMapping ); super( columnDefinition, length, precision, scale, jdbcMapping );
@ -59,6 +61,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
this.nullable = nullable; this.nullable = nullable;
this.insertable = insertable; this.insertable = insertable;
this.updateable = updateable; this.updateable = updateable;
this.partitioned = partitioned;
this.isFormula = isFormula; this.isFormula = isFormula;
} }
@ -69,6 +72,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
final TypeConfiguration typeConfiguration, final TypeConfiguration typeConfiguration,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
final Dialect dialect, final Dialect dialect,
final SqmFunctionRegistry sqmFunctionRegistry) { final SqmFunctionRegistry sqmFunctionRegistry) {
return from( return from(
@ -79,6 +83,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
typeConfiguration, typeConfiguration,
insertable, insertable,
updateable, updateable,
partitioned,
dialect, dialect,
sqmFunctionRegistry sqmFunctionRegistry
); );
@ -92,6 +97,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
final TypeConfiguration typeConfiguration, final TypeConfiguration typeConfiguration,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
final Dialect dialect, final Dialect dialect,
final SqmFunctionRegistry sqmFunctionRegistry) { final SqmFunctionRegistry sqmFunctionRegistry) {
return from( return from(
@ -105,6 +111,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
typeConfiguration, typeConfiguration,
insertable, insertable,
updateable, updateable,
partitioned,
dialect, dialect,
sqmFunctionRegistry sqmFunctionRegistry
); );
@ -119,6 +126,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
final TypeConfiguration typeConfiguration, final TypeConfiguration typeConfiguration,
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean partitioned,
final Dialect dialect, final Dialect dialect,
final SqmFunctionRegistry sqmFunctionRegistry) { final SqmFunctionRegistry sqmFunctionRegistry) {
final String columnExpression; final String columnExpression;
@ -160,6 +168,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
isNullable, isNullable,
insertable, insertable,
updateable, updateable,
partitioned,
selectable.isFormula(), selectable.isFormula(),
jdbcMapping jdbcMapping
); );
@ -224,4 +233,9 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select
public boolean isUpdateable() { public boolean isUpdateable() {
return updateable; return updateable;
} }
@Override
public boolean isPartitioned() {
return partitioned;
}
} }

View File

@ -90,6 +90,7 @@ public class SelectableMappingsImpl implements SelectableMappings {
typeConfiguration, typeConfiguration,
insertable[i], insertable[i],
updateable[i], updateable[i],
false,
dialect, dialect,
sqmFunctionRegistry sqmFunctionRegistry
); );
@ -120,6 +121,7 @@ public class SelectableMappingsImpl implements SelectableMappings {
typeConfiguration, typeConfiguration,
false, false,
false, false,
false,
dialect, dialect,
sqmFunctionRegistry sqmFunctionRegistry
); );

View File

@ -546,6 +546,11 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
return keySide.getModelPart().isUpdateable(); return keySide.getModelPart().isUpdateable();
} }
@Override
public boolean isPartitioned() {
return keySide.getModelPart().isPartitioned();
}
@Override @Override
public String getCustomReadExpression() { public String getCustomReadExpression() {
return keySide.getModelPart().getCustomReadExpression(); return keySide.getModelPart().getCustomReadExpression();

View File

@ -276,4 +276,9 @@ public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping implements
public AttributeMapping asAttributeMapping() { public AttributeMapping asAttributeMapping() {
return getAttribute(); return getAttribute();
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return attribute.hasPartitionedSelectionMapping();
}
} }

View File

@ -716,6 +716,11 @@ public class ToOneAttributeMapping
return canUseParentTableGroup; return canUseParentTableGroup;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return foreignKeyDescriptor.hasPartitionedSelectionMapping();
}
public String getReferencedPropertyName() { public String getReferencedPropertyName() {
return referencedPropertyName; return referencedPropertyName;
} }

View File

@ -333,6 +333,7 @@ public abstract class AbstractEntityPersister
private final boolean hasFormulaProperties; private final boolean hasFormulaProperties;
protected final int batchSize; protected final int batchSize;
private final boolean hasSubselectLoadableCollections; private final boolean hasSubselectLoadableCollections;
private final boolean hasPartitionedSelectionMapping;
protected final String rowIdName; protected final String rowIdName;
// The optional SQL string defined in the where attribute // The optional SQL string defined in the where attribute
@ -505,6 +506,7 @@ public abstract class AbstractEntityPersister
} }
batchSize = batch; batchSize = batch;
hasSubselectLoadableCollections = bootDescriptor.hasSubselectLoadableCollections(); hasSubselectLoadableCollections = bootDescriptor.hasSubselectLoadableCollections();
hasPartitionedSelectionMapping = bootDescriptor.hasPartitionedSelectionMapping();
propertyMapping = new BasicEntityPropertyMapping( this ); propertyMapping = new BasicEntityPropertyMapping( this );
@ -5838,6 +5840,10 @@ public abstract class AbstractEntityPersister
); );
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return hasPartitionedSelectionMapping;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Deprecations // Deprecations

View File

@ -10,7 +10,10 @@ import java.util.List;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
import org.hibernate.engine.jdbc.mutation.ParameterUsage;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.persister.entity.AbstractEntityPersister;
@ -111,4 +114,32 @@ public abstract class AbstractMutationCoordinator {
); );
} ); } );
} }
protected void bindPartitionColumnValueBindings(
Object[] loadedState,
SharedSessionContractImplementor session,
JdbcValueBindings jdbcValueBindings) {
if ( entityPersister().hasPartitionedSelectionMapping() ) {
entityPersister().forEachAttributeMapping(
(index, attributeMapping) -> {
if ( attributeMapping.hasPartitionedSelectionMapping() ) {
attributeMapping.decompose(
loadedState[index],
(value, jdbcValueMapping) -> {
if ( jdbcValueMapping.isPartitioned() ) {
jdbcValueBindings.bindValue(
value,
jdbcValueMapping,
ParameterUsage.RESTRICT,
session
);
}
},
session
);
}
}
);
}
}
} }

View File

@ -79,7 +79,7 @@ public class DeleteCoordinator extends AbstractMutationCoordinator {
doDynamicDelete( entity, id, rowId, loadedState, session ); doDynamicDelete( entity, id, rowId, loadedState, session );
} }
else { else {
doStaticDelete( entity, id, version, session ); doStaticDelete( entity, id, entry == null ? null : entry.getLoadedState(), version, session );
} }
} }
@ -253,6 +253,7 @@ public class DeleteCoordinator extends AbstractMutationCoordinator {
protected void doStaticDelete( protected void doStaticDelete(
Object entity, Object entity,
Object id, Object id,
Object[] loadedState,
Object version, Object version,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
final MutationExecutorService mutationExecutorService = session final MutationExecutorService mutationExecutorService = session
@ -287,6 +288,9 @@ public class DeleteCoordinator extends AbstractMutationCoordinator {
if ( applyVersion ) { if ( applyVersion ) {
applyLocking( version, null, mutationExecutor, session ); applyLocking( version, null, mutationExecutor, session );
} }
final JdbcValueBindings jdbcValueBindings = mutationExecutor.getJdbcValueBindings();
bindPartitionColumnValueBindings( loadedState, session, jdbcValueBindings );
applyId( id, null, mutationExecutor, staticOperationGroup, session ); applyId( id, null, mutationExecutor, staticOperationGroup, session );
@ -365,8 +369,20 @@ public class DeleteCoordinator extends AbstractMutationCoordinator {
if ( applyVersion ) { if ( applyVersion ) {
// apply any optimistic locking // apply any optimistic locking
applyOptimisticLocking( deleteGroupBuilder, loadedState, session ); applyOptimisticLocking( deleteGroupBuilder, loadedState, session );
if ( entityPersister().hasPartitionedSelectionMapping() ) {
entityPersister().forEachSelectable(
(selectionIndex, selectableMapping) -> {
if ( selectableMapping.isPartitioned() ) {
final String tableNameForMutation =
entityPersister().physicalTableNameForMutation( selectableMapping );
final RestrictedTableMutationBuilder<?, ?> rootTableMutationBuilder =
deleteGroupBuilder.findTableDetailsBuilder( tableNameForMutation );
rootTableMutationBuilder.addKeyRestrictionLeniently( selectableMapping );
}
}
);
}
} }
// todo (6.2) : apply where + where-fragments // todo (6.2) : apply where + where-fragments
} }

View File

@ -331,6 +331,11 @@ public class EntityTableMapping implements TableMapping {
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override @Override
public String getColumnDefinition() { public String getColumnDefinition() {
return null; return null;

View File

@ -298,6 +298,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
id, id,
rowId, rowId,
values, values,
incomingOldValues,
valuesAnalysis, valuesAnalysis,
session session
); );
@ -625,6 +626,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
Object id, Object id,
Object rowId, Object rowId,
Object[] values, Object[] values,
Object[] oldValues,
UpdateValuesAnalysisImpl valuesAnalysis, UpdateValuesAnalysisImpl valuesAnalysis,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
final MutationExecutorService mutationExecutorService = session.getSessionFactory() final MutationExecutorService mutationExecutorService = session.getSessionFactory()
@ -648,6 +650,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
(position, attribute) -> true, (position, attribute) -> true,
session session
); );
bindPartitionColumnValueBindings( oldValues, session, mutationExecutor.getJdbcValueBindings() );
try { try {
//noinspection SuspiciousMethodCalls //noinspection SuspiciousMethodCalls
@ -836,6 +839,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
(attributeIndex, attribute) -> dirtinessChecker.include( attributeIndex, (SingularAttributeMapping) attribute ), (attributeIndex, attribute) -> dirtinessChecker.include( attributeIndex, (SingularAttributeMapping) attribute ),
session session
); );
bindPartitionColumnValueBindings( oldValues, session, mutationExecutor.getJdbcValueBindings() );
try { try {
mutationExecutor.execute( mutationExecutor.execute(
@ -1028,6 +1032,16 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
"?", "?",
keyColumn.getJdbcMapping() keyColumn.getJdbcMapping()
) ); ) );
}
if ( entityPersister().hasPartitionedSelectionMapping() ) {
entityPersister().forEachSelectable(
(selectionIndex, selectableMapping) -> {
if ( selectableMapping.isPartitioned() ) {
tableUpdateBuilder.addKeyRestrictionLeniently( selectableMapping );
}
}
);
} }
} ); } );
} }
@ -1429,6 +1443,15 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
} ); } );
updateBuilder.addOptimisticLockRestriction( versionMapping ); updateBuilder.addOptimisticLockRestriction( versionMapping );
if ( entityPersister().hasPartitionedSelectionMapping() ) {
entityPersister().forEachSelectable(
(selectionIndex, selectableMapping) -> {
if ( selectableMapping.isPartitioned() ) {
updateBuilder.addKeyRestrictionLeniently( selectableMapping );
}
}
);
}
final RestrictedTableMutation<MutationOperation> mutation = updateBuilder.buildMutation(); final RestrictedTableMutation<MutationOperation> mutation = updateBuilder.buildMutation();

View File

@ -137,6 +137,16 @@ public class AnonymousTupleBasicValuedModelPart implements ModelPart, MappingTyp
return false; return false;
} }
@Override
public boolean isPartitioned() {
return false;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public String getColumnDefinition() { public String getColumnDefinition() {
return null; return null;

View File

@ -360,6 +360,11 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
return null; return null;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
@Override @Override
public <T> DomainResult<T> createDomainResult( public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath, NavigablePath navigablePath,

View File

@ -346,6 +346,11 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
return offset - originalOffset; return offset - originalOffset;
} }
@Override
public boolean hasPartitionedSelectionMapping() {
return false;
}
//-------------------------------- //--------------------------------
// Support for using the anonymous tuple as table reference directly somewhere is not yet implemented // Support for using the anonymous tuple as table reference directly somewhere is not yet implemented
//-------------------------------- //--------------------------------

View File

@ -0,0 +1,111 @@
/*
* 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.sql.partition;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
@DomainModel( annotatedClasses = PartitionKeyTests.PartitionedEntity.class )
@SessionFactory( useCollectingStatementInspector = true )
public class PartitionKeyTests {
@Test
public void test(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
// update
scope.inTransaction( (session) -> {
final PartitionedEntity entity = session.find( PartitionedEntity.class, 1 );
inspector.clear();
entity.setName( "The One" );
} );
checkWherePredicate( inspector );
// delete
scope.inTransaction( (session) -> {
final PartitionedEntity entity = session.find( PartitionedEntity.class, 1 );
inspector.clear();
session.remove( entity );
} );
checkWherePredicate( inspector );
}
private void checkWherePredicate(SQLStatementInspector inspector) {
assertThat( inspector.getSqlQueries() ).hasSize( 1 );
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "tenant_id=?" );
}
@BeforeEach
public void prepareTestData(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new PartitionedEntity( 1, 1, "tbd" ) );
} );
}
@AfterEach
public void dropTestData(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete PartitionedEntity" ).executeUpdate();
} );
}
@Entity( name = "PartitionedEntity" )
@Table( name = "entity_table" )
public static class PartitionedEntity {
@Id
private Integer id;
@PartitionKey
@Column(name = "tenant_id", updatable = false)
private Integer tenantId;
@Basic
private String name;
protected PartitionedEntity() {
// for use by Hibernate
}
public PartitionedEntity(Integer id, Integer tenantId, String name) {
this.id = id;
this.tenantId = tenantId;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getTenantId() {
return tenantId;
}
public void setTenantId(Integer tenantId) {
this.tenantId = tenantId;
}
}
}