Skip to content

Commit

Permalink
#95 - Bind hierarchy details
Browse files Browse the repository at this point in the history
- version
- tenancy
- optimistic locking
- caching
  • Loading branch information
sebersole committed Nov 21, 2023
1 parent 960b4c5 commit b962a56
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.SharedCacheMode;

import static org.hibernate.boot.models.bind.ModelBindingLogging.MODEL_BINDING_LOGGER;
import static org.hibernate.boot.models.bind.internal.binders.IdentifierBinder.bindIdentifier;
Expand Down Expand Up @@ -452,9 +453,39 @@ protected void prepareBinding(ModelBinders modelBinders) {
bindDiscriminatorValue( getManagedType(), getTypeBinding(), modelBinders, getBindingState(), getOptions(), getBindingContext() );
}

bindCacheable( getManagedType(), getTypeBinding(), modelBinders, getOptions(), getBindingState(), getBindingContext() );

super.prepareBinding( modelBinders );
}

private static void bindCacheable(
EntityTypeMetadata managedType,
PersistentClass typeBinding,
ModelBinders modelBinders,
BindingOptions options,
BindingState bindingState,
BindingContext bindingContext) {
final AnnotationUsage<Cacheable> cacheableAnn = managedType.getClassDetails().getAnnotationUsage( Cacheable.class );
final SharedCacheMode sharedCacheMode = bindingState.getMetadataBuildingContext()
.getBuildingOptions()
.getSharedCacheMode();
typeBinding.setCached( isCacheable( sharedCacheMode, cacheableAnn ) );
}

private static boolean isCacheable(SharedCacheMode sharedCacheMode, AnnotationUsage<Cacheable> explicitCacheableAnn) {
return switch ( sharedCacheMode ) {
// all entities should be cached
case ALL -> true;
// Hibernate defaults to ENABLE_SELECTIVE, the only sensible setting
// only entities with @Cacheable(true) should be cached
case ENABLE_SELECTIVE, UNSPECIFIED -> explicitCacheableAnn != null && explicitCacheableAnn.getBoolean( "value" );
// only entities with @Cacheable(false) should not be cached
case DISABLE_SELECTIVE -> explicitCacheableAnn == null || explicitCacheableAnn.getBoolean( "value" );
// treat both NONE and UNSPECIFIED the same
default -> false;
};
}

protected BasicValue getDiscriminatorMapping() {
if ( binding instanceof RootClass rootClass ) {
return (BasicValue) rootClass.getDiscriminator();
Expand Down Expand Up @@ -582,7 +613,7 @@ private static void bindVersion(
}
}

private void bindTenantId(
private static void bindTenantId(
EntityTypeMetadata managedType,
RootClass typeBinding,
ModelBinders modelBinders,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.models.orm.bind.cache;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.boot.internal.InFlightMetadataCollectorImpl;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;

import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.junit.jupiter.api.Test;

import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.Table;

import static jakarta.persistence.InheritanceType.JOINED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE;
import static org.hibernate.models.orm.bind.BindingTestingHelper.checkDomainModel;

/**
* @author Steve Ebersole
*/
public class SimpleCachingTests {
@SuppressWarnings("JUnitMalformedDeclaration")
@Test
@ServiceRegistry
void simpleTest(ServiceRegistryScope scope) {
checkDomainModel(
(context) -> {
final var metadataCollector = context.getMetadataCollector();
final RootClass entityBinding = (RootClass) metadataCollector.getEntityBinding( CacheableEntity.class.getName() );
assertThat( entityBinding.isCached() ).isTrue();
assertThat( entityBinding.getCacheRegionName() ).isEqualTo( "org.hibernate.testing.entity" );
assertThat( entityBinding.getCacheConcurrencyStrategy() ).isEqualToIgnoringCase( "read-write" );
assertThat( entityBinding.getNaturalIdCacheRegionName() ).isEqualTo( "org.hibernate.testing.natural-id" );

final PersistentClass subEntityBinding = metadataCollector.getEntityBinding( CacheableEntitySub.class.getName() );
assertThat( subEntityBinding.isCached() ).isFalse();
},
scope.getRegistry(),
CacheableEntity.class,
CacheableEntitySub.class
);
}

@Entity(name="CacheableEntity")
@Table(name="CacheableEntity")
@Cacheable
@Cache( region = "org.hibernate.testing.entity", usage = READ_WRITE)
@NaturalIdCache( region = "org.hibernate.testing.natural-id" )
@Inheritance(strategy = JOINED)
public static class CacheableEntity {
@Id
private Integer id;
private String name;
}

@Entity(name="CacheableEntitySub")
@Table(name="CacheableEntitySub")
@Cacheable(false)
public static class CacheableEntitySub extends CacheableEntity {
private String someText;
}
}

0 comments on commit b962a56

Please sign in to comment.