HHH-17504 - Ongoing JPA 32 work
HHH-17350 - Work on hibernate-models, XSD and JAXB HHH-16114 - Improve boot metamodel binding HHH-15996 - Develop an abstraction for Annotation in annotation processing HHH-16012 - Develop an abstraction for domain model Class refs HHH-15997 - Support for dynamic models in orm.xml HHH-15698 - Support for entity-name in mapping.xsd
This commit is contained in:
parent
b3241be1f0
commit
cf69c2683d
|
@ -16,8 +16,6 @@ import org.hibernate.annotations.OptimisticLock;
|
|||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.models.AnnotationPlacementException;
|
||||
import org.hibernate.boot.models.bind.internal.binders.BasicValueBinder;
|
||||
import org.hibernate.boot.models.bind.internal.binders.ColumnBinder;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
|
@ -93,41 +91,38 @@ public class AttributeBinding extends Binding {
|
|||
final BasicValue basicValue = new BasicValue( bindingState.getMetadataBuildingContext() );
|
||||
|
||||
final MemberDetails member = attributeMetadata.getMember();
|
||||
bindImplicitJavaType( member, property, basicValue );
|
||||
BasicValueHelper.bindImplicitJavaType( member, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindMutability( member, property, basicValue );
|
||||
bindOptimisticLocking( member, property, basicValue );
|
||||
bindConversion( member, property, basicValue );
|
||||
|
||||
processColumn( member, property, basicValue, primaryTable, Column.class );
|
||||
|
||||
BasicValueBinder.bindJavaType( member, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
BasicValueBinder.bindJdbcType( member, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
BasicValueBinder.bindLob( member, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
BasicValueBinder.bindNationalized(
|
||||
BasicValueHelper.bindJavaType( member, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
BasicValueHelper.bindJdbcType( member, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
BasicValueHelper.bindLob( member, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
BasicValueHelper.bindNationalized(
|
||||
member,
|
||||
property,
|
||||
basicValue,
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
BasicValueBinder.bindEnumerated(
|
||||
BasicValueHelper.bindEnumerated(
|
||||
member,
|
||||
property,
|
||||
basicValue,
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
BasicValueBinder.bindTemporalPrecision(
|
||||
BasicValueHelper.bindTemporalPrecision(
|
||||
member,
|
||||
property,
|
||||
basicValue,
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
BasicValueBinder.bindTimeZoneStorage(
|
||||
BasicValueHelper.bindTimeZoneStorage(
|
||||
member,
|
||||
property,
|
||||
basicValue,
|
||||
|
@ -156,13 +151,6 @@ public class AttributeBinding extends Binding {
|
|||
return getProperty();
|
||||
}
|
||||
|
||||
public static void bindImplicitJavaType(
|
||||
MemberDetails member,
|
||||
@SuppressWarnings("unused") Property property,
|
||||
BasicValue basicValue) {
|
||||
basicValue.setImplicitJavaTypeAccess( (typeConfiguration) -> member.getType().toJavaClass() );
|
||||
}
|
||||
|
||||
private void bindMutability(MemberDetails member, Property property, BasicValue basicValue) {
|
||||
final var mutabilityAnn = member.getAnnotationUsage( Mutability.class );
|
||||
final var immutableAnn = member.getAnnotationUsage( Immutable.class );
|
||||
|
@ -236,9 +224,18 @@ public class AttributeBinding extends Binding {
|
|||
BasicValue basicValue,
|
||||
Table primaryTable,
|
||||
Class<A> annotation) {
|
||||
BasicValueHelper.bindColumn(
|
||||
member,
|
||||
property::getName,
|
||||
basicValue,
|
||||
primaryTable,
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
// todo : implicit column
|
||||
final var columnAnn = member.getAnnotationUsage( annotation );
|
||||
final var column = ColumnBinder.bindColumn( columnAnn, property::getName );
|
||||
final var column = ColumnHelper.bindColumn( columnAnn, property::getName );
|
||||
|
||||
var tableName = BindingHelper.getValue( columnAnn, "table", "" );
|
||||
if ( "".equals( tableName ) || tableName == null ) {
|
||||
|
|
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* 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.boot.models.bind.internal;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.JavaType;
|
||||
import org.hibernate.annotations.JdbcType;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.annotations.Nationalized;
|
||||
import org.hibernate.annotations.TimeZoneColumn;
|
||||
import org.hibernate.annotations.TimeZoneStorage;
|
||||
import org.hibernate.annotations.TimeZoneStorageType;
|
||||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.models.AnnotationPlacementException;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
import org.hibernate.boot.models.bind.spi.TableReference;
|
||||
import org.hibernate.boot.models.categorize.spi.AttributeMetadata;
|
||||
import org.hibernate.boot.models.categorize.spi.EntityTypeMetadata;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.models.ModelsException;
|
||||
import org.hibernate.models.spi.AnnotationUsage;
|
||||
import org.hibernate.models.spi.ClassDetails;
|
||||
import org.hibernate.models.spi.MemberDetails;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static jakarta.persistence.EnumType.ORDINAL;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hibernate.annotations.TimeZoneStorageType.AUTO;
|
||||
import static org.hibernate.annotations.TimeZoneStorageType.COLUMN;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicValueHelper {
|
||||
|
||||
public static final String TENANT_FILTER_NAME = "_tenantId";
|
||||
public static final String TENANT_PARAMETER_NAME = "tenantId";
|
||||
|
||||
public static void bindImplicitJavaType(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
basicValue.setImplicitJavaTypeAccess( (typeConfiguration) -> member.getType().toJavaClass() );
|
||||
}
|
||||
|
||||
public static void bindJavaType(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
// todo : do we need to account for JavaTypeRegistration here?
|
||||
final var javaTypeAnn = member.getAnnotationUsage( JavaType.class );
|
||||
if ( javaTypeAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
basicValue.setExplicitJavaTypeAccess( (typeConfiguration) -> {
|
||||
final var classDetails = javaTypeAnn.getClassDetails( "value" );
|
||||
final Class<BasicJavaType<?>> javaClass = classDetails.toJavaClass();
|
||||
try {
|
||||
return javaClass.getConstructor().newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
final ModelsException modelsException = new ModelsException( "Error instantiating local @JavaType - " + member.getName() );
|
||||
modelsException.addSuppressed( e );
|
||||
throw modelsException;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public static void bindJdbcType(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
// todo : do we need to account for JdbcTypeRegistration here?
|
||||
final var jdbcTypeAnn = member.getAnnotationUsage( JdbcType.class );
|
||||
final var jdbcTypeCodeAnn = member.getAnnotationUsage( JdbcTypeCode.class );
|
||||
|
||||
if ( jdbcTypeAnn != null ) {
|
||||
if ( jdbcTypeCodeAnn != null ) {
|
||||
throw new AnnotationPlacementException(
|
||||
"Illegal combination of @JdbcType and @JdbcTypeCode - " + member.getName()
|
||||
);
|
||||
}
|
||||
|
||||
basicValue.setExplicitJdbcTypeAccess( (typeConfiguration) -> {
|
||||
final var classDetails = jdbcTypeAnn.getClassDetails( "value" );
|
||||
final Class<org.hibernate.type.descriptor.jdbc.JdbcType> javaClass = classDetails.toJavaClass();
|
||||
try {
|
||||
return javaClass.getConstructor().newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
final ModelsException modelsException = new ModelsException( "Error instantiating local @JdbcType - " + member.getName() );
|
||||
modelsException.addSuppressed( e );
|
||||
throw modelsException;
|
||||
}
|
||||
} );
|
||||
}
|
||||
else if ( jdbcTypeCodeAnn != null ) {
|
||||
final Integer typeCode = jdbcTypeCodeAnn.getInteger( "value" );
|
||||
basicValue.setExplicitJdbcTypeCode( typeCode );
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindNationalized(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
if ( member.getAnnotationUsage( Nationalized.class ) != null ) {
|
||||
basicValue.makeNationalized();
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindLob(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
if ( member.getAnnotationUsage( Lob.class ) != null ) {
|
||||
basicValue.makeLob();
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindEnumerated(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
final AnnotationUsage<Enumerated> enumerated = member.getAnnotationUsage( Enumerated.class );
|
||||
if ( enumerated == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
basicValue.setEnumerationStyle( enumerated.getEnum( "value", ORDINAL ) );
|
||||
}
|
||||
|
||||
public static void bindTemporalPrecision(
|
||||
MemberDetails member,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
final AnnotationUsage<Temporal> temporalAnn = member.getAnnotationUsage( Temporal.class );
|
||||
if ( temporalAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//noinspection deprecation
|
||||
final TemporalType precision = temporalAnn.getEnum( "value" );
|
||||
basicValue.setTemporalPrecision( precision );
|
||||
}
|
||||
|
||||
public static void bindTimeZoneStorage(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
final AnnotationUsage<TimeZoneStorage> storageAnn = member.getAnnotationUsage( TimeZoneStorage.class );
|
||||
final AnnotationUsage<TimeZoneColumn> columnAnn = member.getAnnotationUsage( TimeZoneColumn.class );
|
||||
if ( storageAnn != null ) {
|
||||
final TimeZoneStorageType strategy = storageAnn.getEnum( "value", AUTO );
|
||||
if ( strategy != COLUMN && columnAnn != null ) {
|
||||
throw new AnnotationPlacementException(
|
||||
"Illegal combination of @TimeZoneStorage(" + strategy.name() + ") and @TimeZoneColumn"
|
||||
);
|
||||
}
|
||||
basicValue.setTimeZoneStorageType( strategy );
|
||||
}
|
||||
|
||||
if ( columnAnn != null ) {
|
||||
final org.hibernate.mapping.Column column = (org.hibernate.mapping.Column) basicValue.getColumn();
|
||||
column.setName( columnAnn.getString( "name", property.getName() + "_tz" ) );
|
||||
column.setSqlType( columnAnn.getString( "columnDefinition", (String) null ) );
|
||||
|
||||
final var tableName = columnAnn.getString( "table", (String) null );
|
||||
TableReference tableByName = null;
|
||||
if ( tableName != null ) {
|
||||
final Identifier identifier = Identifier.toIdentifier( tableName );
|
||||
tableByName = bindingState.getTableByName( identifier.getCanonicalName() );
|
||||
basicValue.setTable( tableByName.table() );
|
||||
}
|
||||
|
||||
property.setInsertable( columnAnn.getBoolean( "insertable", true ) );
|
||||
property.setUpdateable( columnAnn.getBoolean( "updatable", true ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindConversion(
|
||||
MemberDetails member,
|
||||
@SuppressWarnings("unused") BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
// todo : do we need to account for auto-applied converters here?
|
||||
final var convertAnn = member.getAnnotationUsage( Convert.class );
|
||||
if ( convertAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( convertAnn.getBoolean( "disableConversion" ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( convertAnn.getString( "attributeName" ) != null ) {
|
||||
throw new ModelsException( "@Convert#attributeName should not be specified on basic mappings - " + member.getName() );
|
||||
}
|
||||
|
||||
final ClassDetails converterClassDetails = convertAnn.getClassDetails( "converter" );
|
||||
final Class<AttributeConverter<?, ?>> javaClass = converterClassDetails.toJavaClass();
|
||||
basicValue.setJpaAttributeConverterDescriptor( new ClassBasedConverterDescriptor(
|
||||
javaClass,
|
||||
bindingContext.getClassmateContext()
|
||||
) );
|
||||
}
|
||||
|
||||
public static org.hibernate.mapping.Column bindColumn(
|
||||
MemberDetails member,
|
||||
Supplier<String> defaultNameSupplier,
|
||||
BasicValue basicValue,
|
||||
Table primaryTable,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
return bindColumn(
|
||||
member,
|
||||
Column.class,
|
||||
defaultNameSupplier,
|
||||
basicValue,
|
||||
primaryTable,
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
}
|
||||
|
||||
public static <A extends Annotation> org.hibernate.mapping.Column bindColumn(
|
||||
MemberDetails member,
|
||||
Class<A> annotationType,
|
||||
Supplier<String> defaultNameSupplier,
|
||||
BasicValue basicValue,
|
||||
Table primaryTable,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
final var columnAnn = member.getAnnotationUsage( annotationType );
|
||||
final var column = ColumnHelper.bindColumn( columnAnn, defaultNameSupplier );
|
||||
|
||||
var tableName = BindingHelper.getValue( columnAnn, "table", "" );
|
||||
if ( StringHelper.isEmpty( tableName ) ) {
|
||||
basicValue.setTable( primaryTable );
|
||||
}
|
||||
else {
|
||||
final Identifier identifier = Identifier.toIdentifier( tableName );
|
||||
final TableReference tableByName = bindingState.getTableByName( identifier.getCanonicalName() );
|
||||
basicValue.setTable( tableByName.table() );
|
||||
}
|
||||
|
||||
basicValue.addColumn( column );
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
public static void bindTenantId(
|
||||
EntityTypeMetadata managedType,
|
||||
RootClass rootClass,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AttributeMetadata tenantIdAttribute = managedType.getHierarchy().getTenantIdAttribute();
|
||||
if ( tenantIdAttribute == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final InFlightMetadataCollector collector = bindingState.getMetadataBuildingContext().getMetadataCollector();
|
||||
final TypeConfiguration typeConfiguration = collector.getTypeConfiguration();
|
||||
|
||||
final MemberDetails memberDetails = tenantIdAttribute.getMember();
|
||||
final String returnedClassName = memberDetails.getType().getClassName();
|
||||
final BasicType<Object> tenantIdType = typeConfiguration
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( returnedClassName );
|
||||
|
||||
final FilterDefinition filterDefinition = collector.getFilterDefinition( TENANT_FILTER_NAME );
|
||||
if ( filterDefinition == null ) {
|
||||
collector.addFilterDefinition( new FilterDefinition(
|
||||
TENANT_FILTER_NAME,
|
||||
"",
|
||||
singletonMap( TENANT_PARAMETER_NAME, tenantIdType )
|
||||
) );
|
||||
}
|
||||
else {
|
||||
final org.hibernate.type.descriptor.java.JavaType<?> tenantIdTypeJtd = tenantIdType.getJavaTypeDescriptor();
|
||||
final org.hibernate.type.descriptor.java.JavaType<?> parameterJtd = filterDefinition
|
||||
.getParameterJdbcMapping( TENANT_PARAMETER_NAME )
|
||||
.getJavaTypeDescriptor();
|
||||
if ( !parameterJtd.getJavaTypeClass().equals( tenantIdTypeJtd.getJavaTypeClass() ) ) {
|
||||
throw new MappingException(
|
||||
"all @TenantId fields must have the same type: "
|
||||
+ parameterJtd.getJavaType().getTypeName()
|
||||
+ " differs from "
|
||||
+ tenantIdTypeJtd.getJavaType().getTypeName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final Property property = new Property();
|
||||
rootClass.addProperty( property );
|
||||
property.setName( tenantIdAttribute.getName() );
|
||||
|
||||
final BasicValue basicValue = new BasicValue( bindingState.getMetadataBuildingContext(), rootClass.getRootTable() );
|
||||
property.setValue( basicValue );
|
||||
|
||||
bindImplicitJavaType( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJavaType( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJdbcType( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
bindConversion( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindEnumerated( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
BasicValueHelper.bindColumn(
|
||||
memberDetails,
|
||||
property::getName,
|
||||
basicValue,
|
||||
rootClass.getRootTable(),
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
|
||||
property.resetUpdateable( false );
|
||||
property.resetOptional( false );
|
||||
}
|
||||
|
||||
public static void bindVersion(
|
||||
EntityTypeMetadata typeMetadata,
|
||||
RootClass rootClass,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AttributeMetadata versionAttribute = typeMetadata.getHierarchy().getVersionAttribute();
|
||||
if ( versionAttribute == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Property property = new Property();
|
||||
property.setName( versionAttribute.getName() );
|
||||
rootClass.setVersion( property );
|
||||
rootClass.addProperty( property );
|
||||
|
||||
final BasicValue basicValue = new BasicValue(
|
||||
bindingState.getMetadataBuildingContext(),
|
||||
rootClass.getRootTable()
|
||||
);
|
||||
property.setValue( basicValue );
|
||||
|
||||
final MemberDetails memberDetails = versionAttribute.getMember();
|
||||
bindImplicitJavaType( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJavaType( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJdbcType( memberDetails, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
final org.hibernate.mapping.Column column = bindColumn(
|
||||
memberDetails,
|
||||
property::getName,
|
||||
basicValue,
|
||||
rootClass.getRootTable(),
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
// force it to be non-nullable
|
||||
column.setNullable( false );
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright: Red Hat Inc. and Hibernate Authors
|
||||
* 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.boot.models.bind.internal.binders;
|
||||
package org.hibernate.boot.models.bind.internal;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -28,7 +28,7 @@ import static org.hibernate.internal.util.NullnessHelper.nullif;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ColumnBinder {
|
||||
public class ColumnHelper {
|
||||
public static Column bindColumn(
|
||||
AnnotationUsage<?> annotationUsage,
|
||||
Supplier<String> defaultNameSupplier) {
|
||||
|
@ -90,7 +90,7 @@ public class ColumnBinder {
|
|||
return nullif( columnAnnotation.getAttributeValue( "name" ), defaultNameSupplier );
|
||||
}
|
||||
|
||||
private ColumnBinder() {
|
||||
private ColumnHelper() {
|
||||
}
|
||||
|
||||
public static DiscriminatorType bindDiscriminatorColumn(
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.boot.models.bind.internal;
|
||||
|
||||
import org.hibernate.boot.models.bind.internal.binders.BasicValueBinder;
|
||||
import org.hibernate.boot.models.bind.internal.binders.ColumnBinder;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
|
@ -106,7 +104,7 @@ public class IdentifierBinding extends Binding {
|
|||
final PrimaryKey primaryKey = table.getPrimaryKey();
|
||||
|
||||
final AnnotationUsage<Column> idColumnAnn = idAttributeMember.getAnnotationUsage( Column.class );
|
||||
final org.hibernate.mapping.Column column = ColumnBinder.bindColumn(
|
||||
final org.hibernate.mapping.Column column = ColumnHelper.bindColumn(
|
||||
idColumnAnn,
|
||||
() -> "id",
|
||||
true,
|
||||
|
@ -115,10 +113,10 @@ public class IdentifierBinding extends Binding {
|
|||
idValue.addColumn( column, true, false );
|
||||
primaryKey.addColumn( column );
|
||||
|
||||
AttributeBinding.bindImplicitJavaType( idAttributeMember, idProperty, idValue );
|
||||
BasicValueBinder.bindJavaType( idAttributeMember, idProperty, idValue, options, state, context );
|
||||
BasicValueBinder.bindJdbcType( idAttributeMember, idProperty, idValue, options, state, context );
|
||||
BasicValueBinder.bindNationalized( idAttributeMember, idProperty, idValue, options, state, context );
|
||||
BasicValueHelper.bindImplicitJavaType( idAttributeMember, idValue, options, state, context );
|
||||
BasicValueHelper.bindJavaType( idAttributeMember, idValue, options, state, context );
|
||||
BasicValueHelper.bindJdbcType( idAttributeMember, idValue, options, state, context );
|
||||
BasicValueHelper.bindNationalized( idAttributeMember, idValue, options, state, context );
|
||||
|
||||
return idValue;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
|||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.models.bind.internal.binders.ColumnBinder;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
|
@ -40,8 +39,8 @@ import jakarta.persistence.DiscriminatorType;
|
|||
import jakarta.persistence.InheritanceType;
|
||||
|
||||
import static org.hibernate.boot.models.bind.ModelBindingLogging.MODEL_BINDING_LOGGER;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.TenantIdBinder.bindTenantId;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.VersionBinder.bindVersion;
|
||||
import static org.hibernate.boot.models.bind.internal.BasicValueHelper.bindTenantId;
|
||||
import static org.hibernate.boot.models.bind.internal.BasicValueHelper.bindVersion;
|
||||
import static org.hibernate.internal.util.StringHelper.coalesce;
|
||||
|
||||
/**
|
||||
|
@ -304,7 +303,7 @@ public class RootEntityBinding extends EntityBinding {
|
|||
final BasicValue value = new BasicValue( bindingState.getMetadataBuildingContext(), rootClass.getIdentityTable() );
|
||||
rootClass.setDiscriminator( value );
|
||||
|
||||
final DiscriminatorType discriminatorType = ColumnBinder.bindDiscriminatorColumn(
|
||||
final DiscriminatorType discriminatorType = ColumnHelper.bindDiscriminatorColumn(
|
||||
bindingContext,
|
||||
formulaAnn,
|
||||
value,
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.models.bind.internal.binders.ColumnBinder;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
|
@ -172,10 +171,10 @@ public class SubclassEntityBinding extends EntityBinding {
|
|||
targetColumn,
|
||||
joinColumnAnns
|
||||
);
|
||||
pkColumn = ColumnBinder.bindColumn( joinColumnAnn, targetColumn::getName, true, false );
|
||||
pkColumn = ColumnHelper.bindColumn( joinColumnAnn, targetColumn::getName, true, false );
|
||||
}
|
||||
else {
|
||||
pkColumn = ColumnBinder.bindColumn( null, targetColumn::getName, true, false );
|
||||
pkColumn = ColumnHelper.bindColumn( null, targetColumn::getName, true, false );
|
||||
}
|
||||
primaryKey.addColumn( pkColumn );
|
||||
}
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright: Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.boot.models.bind.internal.binders;
|
||||
|
||||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.models.bind.internal.BindingHelper;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
import org.hibernate.boot.models.bind.spi.TableReference;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.models.ModelsException;
|
||||
import org.hibernate.models.spi.ClassDetails;
|
||||
import org.hibernate.models.spi.MemberDetails;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AttributeBinder {
|
||||
public static void bindImplicitJavaType(
|
||||
MemberDetails member,
|
||||
@SuppressWarnings("unused") Property property,
|
||||
BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
basicValue.setImplicitJavaTypeAccess( (typeConfiguration) -> member.getType().toJavaClass() );
|
||||
}
|
||||
|
||||
|
||||
public static org.hibernate.mapping.Column processColumn(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
Table primaryTable,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
// todo : implicit column
|
||||
final var columnAnn = member.getAnnotationUsage( Column.class );
|
||||
final var column = ColumnBinder.bindColumn( columnAnn, property::getName );
|
||||
|
||||
var tableName = BindingHelper.getValue( columnAnn, "table", "" );
|
||||
if ( "".equals( tableName ) || tableName == null ) {
|
||||
basicValue.setTable( primaryTable );
|
||||
}
|
||||
else {
|
||||
final Identifier identifier = Identifier.toIdentifier( tableName );
|
||||
final TableReference tableByName = bindingState.getTableByName( identifier.getCanonicalName() );
|
||||
basicValue.setTable( tableByName.table() );
|
||||
}
|
||||
|
||||
basicValue.addColumn( column );
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
public static void bindConversion(
|
||||
MemberDetails member,
|
||||
@SuppressWarnings("unused") Property property,
|
||||
@SuppressWarnings("unused") BasicValue basicValue,
|
||||
@SuppressWarnings("unused") BindingOptions bindingOptions,
|
||||
@SuppressWarnings("unused") BindingState bindingState,
|
||||
@SuppressWarnings("unused") BindingContext bindingContext) {
|
||||
// todo : do we need to account for auto-applied converters here?
|
||||
final var convertAnn = member.getAnnotationUsage( Convert.class );
|
||||
if ( convertAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( convertAnn.getBoolean( "disableConversion" ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( convertAnn.getString( "attributeName" ) != null ) {
|
||||
throw new ModelsException( "@Convert#attributeName should not be specified on basic mappings - " + member.getName() );
|
||||
}
|
||||
|
||||
final ClassDetails converterClassDetails = convertAnn.getClassDetails( "converter" );
|
||||
final Class<AttributeConverter<?, ?>> javaClass = converterClassDetails.toJavaClass();
|
||||
basicValue.setJpaAttributeConverterDescriptor( new ClassBasedConverterDescriptor(
|
||||
javaClass,
|
||||
bindingContext.getClassmateContext()
|
||||
) );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright: Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.boot.models.bind.internal.binders;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.hibernate.annotations.JavaType;
|
||||
import org.hibernate.annotations.JdbcType;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.annotations.Nationalized;
|
||||
import org.hibernate.annotations.TimeZoneColumn;
|
||||
import org.hibernate.annotations.TimeZoneStorage;
|
||||
import org.hibernate.annotations.TimeZoneStorageType;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.models.AnnotationPlacementException;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
import org.hibernate.boot.models.bind.spi.TableReference;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.models.ModelsException;
|
||||
import org.hibernate.models.spi.AnnotationUsage;
|
||||
import org.hibernate.models.spi.MemberDetails;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static jakarta.persistence.EnumType.ORDINAL;
|
||||
import static org.hibernate.annotations.TimeZoneStorageType.AUTO;
|
||||
import static org.hibernate.annotations.TimeZoneStorageType.COLUMN;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicValueBinder {
|
||||
|
||||
public static void bindJavaType(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
// todo : do we need to account for JavaTypeRegistration here?
|
||||
final var javaTypeAnn = member.getAnnotationUsage( JavaType.class );
|
||||
if ( javaTypeAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
basicValue.setExplicitJavaTypeAccess( (typeConfiguration) -> {
|
||||
final var classDetails = javaTypeAnn.getClassDetails( "value" );
|
||||
final Class<BasicJavaType<?>> javaClass = classDetails.toJavaClass();
|
||||
try {
|
||||
return javaClass.getConstructor().newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
final ModelsException modelsException = new ModelsException( "Error instantiating local @JavaType - " + member.getName() );
|
||||
modelsException.addSuppressed( e );
|
||||
throw modelsException;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public static void bindJdbcType(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
// todo : do we need to account for JdbcTypeRegistration here?
|
||||
final var jdbcTypeAnn = member.getAnnotationUsage( JdbcType.class );
|
||||
final var jdbcTypeCodeAnn = member.getAnnotationUsage( JdbcTypeCode.class );
|
||||
|
||||
if ( jdbcTypeAnn != null ) {
|
||||
if ( jdbcTypeCodeAnn != null ) {
|
||||
throw new AnnotationPlacementException(
|
||||
"Illegal combination of @JdbcType and @JdbcTypeCode - " + member.getName()
|
||||
);
|
||||
}
|
||||
|
||||
basicValue.setExplicitJdbcTypeAccess( (typeConfiguration) -> {
|
||||
final var classDetails = jdbcTypeAnn.getClassDetails( "value" );
|
||||
final Class<org.hibernate.type.descriptor.jdbc.JdbcType> javaClass = classDetails.toJavaClass();
|
||||
try {
|
||||
return javaClass.getConstructor().newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
final ModelsException modelsException = new ModelsException( "Error instantiating local @JdbcType - " + member.getName() );
|
||||
modelsException.addSuppressed( e );
|
||||
throw modelsException;
|
||||
}
|
||||
} );
|
||||
}
|
||||
else if ( jdbcTypeCodeAnn != null ) {
|
||||
final Integer typeCode = jdbcTypeCodeAnn.getInteger( "value" );
|
||||
basicValue.setExplicitJdbcTypeCode( typeCode );
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindNationalized(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
if ( member.getAnnotationUsage( Nationalized.class ) != null ) {
|
||||
basicValue.makeNationalized();
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindLob(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
if ( member.getAnnotationUsage( Lob.class ) != null ) {
|
||||
basicValue.makeLob();
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindEnumerated(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AnnotationUsage<Enumerated> enumerated = member.getAnnotationUsage( Enumerated.class );
|
||||
if ( enumerated == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
basicValue.setEnumerationStyle( enumerated.getEnum( "value", ORDINAL ) );
|
||||
}
|
||||
|
||||
public static void bindTemporalPrecision(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AnnotationUsage<Temporal> temporalAnn = member.getAnnotationUsage( Temporal.class );
|
||||
if ( temporalAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//noinspection deprecation
|
||||
final TemporalType precision = temporalAnn.getEnum( "value" );
|
||||
basicValue.setTemporalPrecision( precision );
|
||||
}
|
||||
|
||||
public static void bindTimeZoneStorage(
|
||||
MemberDetails member,
|
||||
Property property,
|
||||
BasicValue basicValue,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AnnotationUsage<TimeZoneStorage> storageAnn = member.getAnnotationUsage( TimeZoneStorage.class );
|
||||
final AnnotationUsage<TimeZoneColumn> columnAnn = member.getAnnotationUsage( TimeZoneColumn.class );
|
||||
if ( storageAnn != null ) {
|
||||
final TimeZoneStorageType strategy = storageAnn.getEnum( "value", AUTO );
|
||||
if ( strategy != COLUMN && columnAnn != null ) {
|
||||
throw new AnnotationPlacementException(
|
||||
"Illegal combination of @TimeZoneStorage(" + strategy.name() + ") and @TimeZoneColumn"
|
||||
);
|
||||
}
|
||||
basicValue.setTimeZoneStorageType( strategy );
|
||||
}
|
||||
|
||||
if ( columnAnn != null ) {
|
||||
final org.hibernate.mapping.Column column = (org.hibernate.mapping.Column) basicValue.getColumn();
|
||||
column.setName( columnAnn.getString( "name", property.getName() + "_tz" ) );
|
||||
column.setSqlType( columnAnn.getString( "columnDefinition", (String) null ) );
|
||||
|
||||
final var tableName = columnAnn.getString( "table", (String) null );
|
||||
TableReference tableByName = null;
|
||||
if ( tableName != null ) {
|
||||
final Identifier identifier = Identifier.toIdentifier( tableName );
|
||||
tableByName = bindingState.getTableByName( identifier.getCanonicalName() );
|
||||
basicValue.setTable( tableByName.table() );
|
||||
}
|
||||
|
||||
property.setInsertable( columnAnn.getBoolean( "insertable", true ) );
|
||||
property.setUpdateable( columnAnn.getBoolean( "updatable", true ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright: Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.boot.models.bind.internal.binders;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
import org.hibernate.boot.models.categorize.spi.AttributeMetadata;
|
||||
import org.hibernate.boot.models.categorize.spi.EntityTypeMetadata;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.models.spi.MemberDetails;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.AttributeBinder.bindConversion;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.AttributeBinder.bindImplicitJavaType;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.AttributeBinder.processColumn;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.BasicValueBinder.bindEnumerated;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.BasicValueBinder.bindJavaType;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.BasicValueBinder.bindJdbcType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TenantIdBinder {
|
||||
public static final String FILTER_NAME = "_tenantId";
|
||||
public static final String PARAMETER_NAME = "tenantId";
|
||||
|
||||
public static void bindTenantId(
|
||||
EntityTypeMetadata managedType,
|
||||
RootClass rootClass,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AttributeMetadata tenantIdAttribute = managedType.getHierarchy().getTenantIdAttribute();
|
||||
if ( tenantIdAttribute == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
bindTenantId( tenantIdAttribute, rootClass, bindingOptions, bindingState, bindingContext );
|
||||
}
|
||||
|
||||
public static void bindTenantId(
|
||||
AttributeMetadata attributeMetadata,
|
||||
RootClass rootClass,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final InFlightMetadataCollector collector = bindingState.getMetadataBuildingContext().getMetadataCollector();
|
||||
final TypeConfiguration typeConfiguration = collector.getTypeConfiguration();
|
||||
|
||||
final MemberDetails memberDetails = attributeMetadata.getMember();
|
||||
final String returnedClassName = memberDetails.getType().getClassName();
|
||||
final BasicType<Object> tenantIdType = typeConfiguration
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( returnedClassName );
|
||||
|
||||
final FilterDefinition filterDefinition = collector.getFilterDefinition( FILTER_NAME );
|
||||
if ( filterDefinition == null ) {
|
||||
collector.addFilterDefinition( new FilterDefinition(
|
||||
FILTER_NAME,
|
||||
"",
|
||||
singletonMap( PARAMETER_NAME, tenantIdType )
|
||||
) );
|
||||
}
|
||||
else {
|
||||
final JavaType<?> tenantIdTypeJtd = tenantIdType.getJavaTypeDescriptor();
|
||||
final JavaType<?> parameterJtd = filterDefinition
|
||||
.getParameterJdbcMapping( PARAMETER_NAME )
|
||||
.getJavaTypeDescriptor();
|
||||
if ( !parameterJtd.getJavaTypeClass().equals( tenantIdTypeJtd.getJavaTypeClass() ) ) {
|
||||
throw new MappingException(
|
||||
"all @TenantId fields must have the same type: "
|
||||
+ parameterJtd.getJavaType().getTypeName()
|
||||
+ " differs from "
|
||||
+ tenantIdTypeJtd.getJavaType().getTypeName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final Property property = new Property();
|
||||
rootClass.addProperty( property );
|
||||
property.setName( attributeMetadata.getName() );
|
||||
|
||||
final BasicValue basicValue = new BasicValue( bindingState.getMetadataBuildingContext(), rootClass.getRootTable() );
|
||||
property.setValue( basicValue );
|
||||
|
||||
bindImplicitJavaType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJavaType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJdbcType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
bindConversion( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindEnumerated( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
processColumn(
|
||||
memberDetails,
|
||||
property,
|
||||
basicValue,
|
||||
rootClass.getRootTable(),
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
|
||||
property.resetUpdateable( false );
|
||||
property.resetOptional( false );
|
||||
}
|
||||
|
||||
public static void bindTenantId(
|
||||
AttributeMetadata attributeMetadata,
|
||||
EntityTypeMetadata managedType,
|
||||
RootClass typeBinding,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
bindTenantId( attributeMetadata, typeBinding, bindingOptions, bindingState, bindingContext );
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright: Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.boot.models.bind.internal.binders;
|
||||
|
||||
import org.hibernate.boot.models.bind.spi.BindingContext;
|
||||
import org.hibernate.boot.models.bind.spi.BindingOptions;
|
||||
import org.hibernate.boot.models.bind.spi.BindingState;
|
||||
import org.hibernate.boot.models.categorize.spi.AttributeMetadata;
|
||||
import org.hibernate.boot.models.categorize.spi.EntityTypeMetadata;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.models.spi.MemberDetails;
|
||||
|
||||
import static org.hibernate.boot.models.bind.internal.binders.AttributeBinder.bindImplicitJavaType;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.AttributeBinder.processColumn;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.BasicValueBinder.bindJavaType;
|
||||
import static org.hibernate.boot.models.bind.internal.binders.BasicValueBinder.bindJdbcType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class VersionBinder {
|
||||
public static void bindVersion(
|
||||
EntityTypeMetadata typeMetadata,
|
||||
RootClass rootClass,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final AttributeMetadata versionAttribute = typeMetadata.getHierarchy().getVersionAttribute();
|
||||
if ( versionAttribute == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
bindVersion( versionAttribute, rootClass, bindingOptions, bindingState, bindingContext );
|
||||
}
|
||||
|
||||
public static void bindVersion(
|
||||
AttributeMetadata versionAttribute,
|
||||
RootClass typeBinding,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final Property property = new Property();
|
||||
property.setName( versionAttribute.getName() );
|
||||
typeBinding.setVersion( property );
|
||||
typeBinding.addProperty( property );
|
||||
|
||||
final BasicValue basicValue = new BasicValue(
|
||||
bindingState.getMetadataBuildingContext(),
|
||||
typeBinding.getRootTable()
|
||||
);
|
||||
property.setValue( basicValue );
|
||||
|
||||
final MemberDetails memberDetails = versionAttribute.getMember();
|
||||
bindImplicitJavaType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJavaType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJdbcType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
final org.hibernate.mapping.Column column = processColumn(
|
||||
memberDetails,
|
||||
property,
|
||||
basicValue,
|
||||
typeBinding.getRootTable(),
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
// force it to be non-nullable
|
||||
column.setNullable( false );
|
||||
}
|
||||
|
||||
public static void bindVersion(
|
||||
AttributeMetadata attributeMetadata,
|
||||
EntityTypeMetadata managedType,
|
||||
RootClass typeBinding,
|
||||
BindingOptions bindingOptions,
|
||||
BindingState bindingState,
|
||||
BindingContext bindingContext) {
|
||||
final Property property = new Property();
|
||||
property.setName( attributeMetadata.getName() );
|
||||
typeBinding.setVersion( property );
|
||||
typeBinding.addProperty( property );
|
||||
|
||||
final BasicValue basicValue = new BasicValue(
|
||||
bindingState.getMetadataBuildingContext(),
|
||||
typeBinding.getRootTable()
|
||||
);
|
||||
property.setValue( basicValue );
|
||||
|
||||
final MemberDetails memberDetails = attributeMetadata.getMember();
|
||||
bindImplicitJavaType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJavaType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
bindJdbcType( memberDetails, property, basicValue, bindingOptions, bindingState, bindingContext );
|
||||
|
||||
final org.hibernate.mapping.Column column = processColumn(
|
||||
memberDetails,
|
||||
property,
|
||||
basicValue,
|
||||
typeBinding.getRootTable(),
|
||||
bindingOptions,
|
||||
bindingState,
|
||||
bindingContext
|
||||
);
|
||||
// force it to be non-nullable
|
||||
column.setNullable( false );
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
package org.hibernate.orm.test.boot.models.bind.tenancy;
|
||||
|
||||
import org.hibernate.annotations.TenantId;
|
||||
import org.hibernate.boot.models.bind.internal.binders.TenantIdBinder;
|
||||
import org.hibernate.boot.models.bind.internal.BasicValueHelper;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
|
@ -38,7 +38,7 @@ public class SimpleTenancyTests {
|
|||
(context) -> {
|
||||
var metadataCollector = context.getMetadataCollector();
|
||||
|
||||
assertThat( metadataCollector.getFilterDefinition( TenantIdBinder.FILTER_NAME ) ).isNotNull();
|
||||
assertThat( metadataCollector.getFilterDefinition( BasicValueHelper.TENANT_FILTER_NAME ) ).isNotNull();
|
||||
|
||||
final PersistentClass entityBinding = metadataCollector.getEntityBinding( ProtectedEntity.class.getName() );
|
||||
final Property tenantProperty = entityBinding.getProperty( "tenant" );
|
||||
|
@ -65,7 +65,7 @@ public class SimpleTenancyTests {
|
|||
(context) -> {
|
||||
var metadataCollector = context.getMetadataCollector();
|
||||
|
||||
assertThat( metadataCollector.getFilterDefinition( TenantIdBinder.FILTER_NAME ) ).isNotNull();
|
||||
assertThat( metadataCollector.getFilterDefinition( BasicValueHelper.TENANT_FILTER_NAME ) ).isNotNull();
|
||||
|
||||
final PersistentClass entityBinding = metadataCollector.getEntityBinding( ProtectedEntityWithColumn.class.getName() );
|
||||
final Property tenantProperty = entityBinding.getProperty( "tenant" );
|
||||
|
|
Loading…
Reference in New Issue