Skip to content

Commit

Permalink
sebersole#26 - Create AnnotationUsage for tenant-id in XML
Browse files Browse the repository at this point in the history
  • Loading branch information
dreab8 authored and sebersole committed Nov 21, 2023
1 parent b962a56 commit 407766c
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLInsert;
import org.hibernate.annotations.SQLUpdate;
import org.hibernate.annotations.TenantId;
import org.hibernate.boot.internal.Abstract;
import org.hibernate.boot.internal.Extends;
import org.hibernate.boot.internal.LimitedCollectionClassification;
Expand All @@ -34,7 +35,9 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbOneToOneImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPersistentAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbTenantIdImpl;
import org.hibernate.boot.models.categorize.spi.JpaEventListenerStyle;
import org.hibernate.boot.models.categorize.xml.internal.attr.BasicAttributeProcessing;
import org.hibernate.boot.models.categorize.xml.internal.attr.BasicIdAttributeProcessing;
import org.hibernate.boot.models.categorize.xml.internal.attr.CommonAttributeProcessing;
import org.hibernate.boot.models.categorize.xml.internal.attr.EmbeddedIdAttributeProcessing;
Expand Down Expand Up @@ -218,6 +221,22 @@ private static void prepareDynamicClass(
classDetails.addField( member );
} );
}

// <tenant-id>
final JaxbTenantIdImpl tenantId = jaxbDynamicEntity.getTenantId();
if ( tenantId != null ) {
final ClassDetails attributeJavaType = determineDynamicAttributeJavaType(
tenantId,
xmlDocumentContext
);
final MapModeFieldDetails member = new MapModeFieldDetails(
tenantId.getName(),
attributeJavaType,
MEMBER_MODIFIERS,
xmlDocumentContext.getModelBuildingContext()
);
classDetails.addField( member );
}
}

final JaxbAttributesContainer attributes = jaxbManagedType.getAttributes();
Expand Down Expand Up @@ -454,9 +473,37 @@ private static void processEntityMetadata(

XmlAnnotationHelper.applyRowId( jaxbEntity.getRowid(), classDetails, xmlDocumentContext );

applyTenantId( classDetails, jaxbEntity, classAccessType, xmlDocumentContext );

// todo : secondary-tables
}

private static void applyTenantId(
MutableClassDetails classDetails,
JaxbEntityImpl jaxbEntity,
AccessType classAccessType,
XmlDocumentContext xmlDocumentContext) {
final JaxbTenantIdImpl jaxbTenantId = jaxbEntity.getTenantId();
if ( jaxbTenantId != null ) {
final MutableMemberDetails memberDetails = XmlProcessingHelper.getAttributeMember(
jaxbTenantId.getName(),
coalesce( jaxbTenantId.getAccess(), classAccessType ),
classDetails
);
XmlProcessingHelper.getOrMakeAnnotation(
TenantId.class,
memberDetails,
xmlDocumentContext
);
BasicAttributeProcessing.processBasicAttribute(
jaxbTenantId,
classDetails,
classAccessType,
xmlDocumentContext
);
}
}


private static void adjustNonDynamicTypeMember(
MutableMemberDetails memberDetails,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.models.orm.xml.dynamic;


import java.util.Set;


import org.hibernate.annotations.TenantId;
import org.hibernate.boot.internal.BootstrapContextImpl;
import org.hibernate.boot.internal.MetadataBuilderImpl;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.models.categorize.spi.CategorizedDomainModel;
import org.hibernate.boot.models.categorize.spi.EntityHierarchy;
import org.hibernate.boot.models.categorize.spi.EntityTypeMetadata;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.models.orm.process.ManagedResourcesImpl;
import org.hibernate.models.spi.AnnotationUsage;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.FieldDetails;


import org.junit.jupiter.api.Test;


import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.FetchType;


import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.boot.models.categorize.spi.ManagedResourcesProcessor.processManagedResources;


public class TenantIdTest {
@Test
void testSimpleDynamicModel() {
final ManagedResources managedResources = new ManagedResourcesImpl.Builder()
.addXmlMappings( "mappings/dynamic/dynamic-tenantid.xml" )
.build();
try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) {
final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl(
serviceRegistry,
new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry )
);
final CategorizedDomainModel categorizedDomainModel = processManagedResources(
managedResources,
bootstrapContext
);

final Set<EntityHierarchy> entityHierarchies = categorizedDomainModel.getEntityHierarchies();
assertThat( entityHierarchies ).hasSize( 2 );

entityHierarchies.forEach(
entityHierarchy -> {
final EntityTypeMetadata root = entityHierarchy.getRoot();
final String entityName = root.getEntityName();

final FieldDetails field = root.getClassDetails().findFieldByName( "tenantId" );

if ( entityName.equals( "EntityWithoutTenantId" ) ) {
assertThat( field ).isNull();
}
else {
final AnnotationUsage<TenantId> tenantIdAnnotationUsage = field.getAnnotationUsage( TenantId.class );

assertThat( tenantIdAnnotationUsage ).isNotNull();

final AnnotationUsage<Basic> basicAnnotationUsage = field.getAnnotationUsage( Basic.class );
assertThat( basicAnnotationUsage ).isNotNull();
assertThat( basicAnnotationUsage.<FetchType>getAttributeValue( "fetch" ) )
.isEqualTo( FetchType.EAGER );
assertThat( basicAnnotationUsage.getBoolean( "optional" ) ).isTrue();

final AnnotationUsage<Column> columnAnnotationUsage = field.getAnnotationUsage( Column.class );
assertThat( basicAnnotationUsage ).isNotNull();
assertThat( columnAnnotationUsage.getString( "name" ) ).isEqualTo( "TENANT_ID" );
assertThat( columnAnnotationUsage.getBoolean( "insertable" ) ).isFalse();
}
}
);
}
}
}
28 changes: 28 additions & 0 deletions src/test/resources/mappings/dynamic/dynamic-tenantid.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ SPDX-License-Identifier: Apache-2.0
~ Copyright: Red Hat Inc. and Hibernate Authors
-->
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping"
version="3.1">
<entity name="EntityWithoutTenantId" metadata-complete="true">
<attributes>
<id name="id"/>
</attributes>
</entity>


<entity name="EntityWithTenantId" metadata-complete="true">

<tenant-id name="tenantId" fetch="EAGER" optional="true">
<column name="TENANT_ID" insertable="false"/>
</tenant-id>

<attributes>
<id name="id"/>
</attributes>
</entity>


</entity-mappings>

0 comments on commit 407766c

Please sign in to comment.