diff --git a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/CollectionDataCachingConfigImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/CollectionDataCachingConfigImpl.java index c86988aaab33..f0a31ef48ba3 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/CollectionDataCachingConfigImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/CollectionDataCachingConfigImpl.java @@ -12,6 +12,8 @@ import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.type.BasicType; +import static org.hibernate.cache.cfg.internal.ComparatorUtil.versionComparator; + /** * @author Steve Ebersole */ @@ -40,10 +42,11 @@ public boolean isVersioned() { } @Override - public Comparator getOwnerVersionComparator() { + public Comparator getOwnerVersionComparator() { if ( isVersioned() ) { - final var type = (BasicType) collectionDescriptor.getOwner().getVersion().getType(); - return type.getJavaTypeDescriptor().getComparator(); + final var type = (BasicType) + collectionDescriptor.getOwner().getVersion().getType(); + return versionComparator( type ); } else { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/ComparatorUtil.java b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/ComparatorUtil.java new file mode 100644 index 000000000000..0ea30c881f0c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/ComparatorUtil.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.cache.cfg.internal; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.hibernate.type.BasicType; + +import java.util.Comparator; + +class ComparatorUtil { + @NonNull + static Comparator versionComparator(BasicType type) { + return (u, v) -> { + final var descriptor = type.getJavaTypeDescriptor(); + final T x; + final T y; + try { + x = descriptor.cast( u ); + y = descriptor.cast( v ); + } + catch (Exception e) { + throw new IllegalArgumentException( "Cached version was not of type " + type.getName(), e ); + } + return descriptor.getComparator().compare( x, y ); + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/DomainDataRegionConfigImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/DomainDataRegionConfigImpl.java index 46319bac9841..5b4652906e07 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/DomainDataRegionConfigImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/DomainDataRegionConfigImpl.java @@ -5,10 +5,13 @@ package org.hibernate.cache.cfg.internal; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Supplier; +import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig; import org.hibernate.cache.cfg.spi.DomainDataCachingConfig; import org.hibernate.cache.cfg.spi.DomainDataRegionConfig; @@ -23,6 +26,7 @@ import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; +import static org.hibernate.cache.cfg.internal.ComparatorUtil.versionComparator; /** * DomainDataRegionConfig implementation @@ -96,12 +100,7 @@ public Builder addEntityConfig(PersistentClass bootEntityDescriptor, AccessType rootEntityName, x -> new EntityDataCachingConfigImpl( rootEntityName, - bootEntityDescriptor.isVersioned() - ? () -> { - final var type = (BasicType) bootEntityDescriptor.getVersion().getType(); - return type.getJavaTypeDescriptor().getComparator(); - } - : null, + versionComparatorAccess( bootEntityDescriptor ), bootEntityDescriptor.isMutable(), accessType ) @@ -116,6 +115,15 @@ public Builder addEntityConfig(PersistentClass bootEntityDescriptor, AccessType return this; } + private @Nullable Supplier> versionComparatorAccess(PersistentClass bootEntityDescriptor) { + return bootEntityDescriptor.isVersioned() + ? () -> { + final var type = (BasicType) + bootEntityDescriptor.getVersion().getType(); + return versionComparator( type ); + } + : null; + } // todo (6.0) : `EntityPersister` and `CollectionPersister` references here should be replaced with `EntityHierarchy` and `PersistentCollectionDescriptor` // diff --git a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/EntityDataCachingConfigImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/EntityDataCachingConfigImpl.java index 456bbffd91e3..8f28662585aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/EntityDataCachingConfigImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/EntityDataCachingConfigImpl.java @@ -20,14 +20,14 @@ public class EntityDataCachingConfigImpl extends AbstractDomainDataCachingConfig implements EntityDataCachingConfig { private final NavigableRole navigableRole; - private final Supplier> versionComparatorAccess; + private final Supplier> versionComparatorAccess; private final boolean isEntityMutable; private final Set cachedTypes = new HashSet<>(); public EntityDataCachingConfigImpl( NavigableRole rootEntityName, - Supplier> versionComparatorAccess, + Supplier> versionComparatorAccess, boolean isEntityMutable, AccessType accessType) { super( accessType ); @@ -37,7 +37,7 @@ public EntityDataCachingConfigImpl( } @Override - public Supplier> getVersionComparatorAccess() { + public Supplier> getVersionComparatorAccess() { return versionComparatorAccess; } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/CollectionDataCachingConfig.java b/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/CollectionDataCachingConfig.java index 53a2067c4a8f..e0319efe0c2e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/CollectionDataCachingConfig.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/CollectionDataCachingConfig.java @@ -16,5 +16,5 @@ public interface CollectionDataCachingConfig extends DomainDataCachingConfig { /** * The comparator to be used with the owning entity's version (if it has one). */ - Comparator getOwnerVersionComparator(); + Comparator getOwnerVersionComparator(); } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/EntityDataCachingConfig.java b/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/EntityDataCachingConfig.java index 1ad5569bc660..47a805fd898c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/EntityDataCachingConfig.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/EntityDataCachingConfig.java @@ -32,7 +32,7 @@ public interface EntityDataCachingConfig extends DomainDataCachingConfig { * version. If the entity is not versioned, then this method * returns {@code null}. */ - Supplier> getVersionComparatorAccess(); + Supplier> getVersionComparatorAccess(); /** * The list of specific subclasses of the root that are actually diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/AbstractReadWriteAccess.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/AbstractReadWriteAccess.java index 539301feaa79..b7dc202d237f 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/AbstractReadWriteAccess.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/AbstractReadWriteAccess.java @@ -37,7 +37,7 @@ protected AbstractReadWriteAccess( super( domainDataRegion, storageAccess ); } - protected abstract Comparator getVersionComparator(); + protected abstract Comparator getVersionComparator(); protected UUID uuid() { return uuid; @@ -262,7 +262,7 @@ public interface Lockable { * Returns true if the enclosed value can be replaced with one of the given version by a * transaction started at the given time. */ - boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator); + boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator); /** * Returns the enclosed value. @@ -315,7 +315,7 @@ public boolean isReadable(long txTimestamp) { } @Override - public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) { + public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) { if ( L2CACHE_LOGGER.isTraceEnabled() ) { L2CACHE_LOGGER.tracef( "Checking writeability of read-write cache item [timestamp='%s', version='%s'] : txTimestamp='%s', newVersion='%s'", @@ -326,7 +326,6 @@ public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versi ); } - //noinspection unchecked return version != null && versionComparator.compare( version, newVersion ) < 0; } @@ -389,7 +388,7 @@ public boolean isReadable(long txTimestamp) { } @Override - public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) { + public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) { if ( L2CACHE_LOGGER.isTraceEnabled() ) { L2CACHE_LOGGER.tracef( "Checking writeability of read-write cache lock [timeout='%s', lockId='%s', version='%s', sourceUuid=%s, multiplicity='%s', unlockTimestamp='%s'] : txTimestamp='%s', newVersion='%s'", @@ -413,7 +412,6 @@ public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versi return false; } - //noinspection unchecked return version == null ? txTimestamp > unlockTimestamp : versionComparator.compare( version, newVersion ) < 0; diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/CollectionReadWriteAccess.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/CollectionReadWriteAccess.java index 9c1ea00ab49d..983238ae204d 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/CollectionReadWriteAccess.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/CollectionReadWriteAccess.java @@ -23,7 +23,7 @@ * @author Steve Ebersole */ public class CollectionReadWriteAccess extends AbstractReadWriteAccess implements CollectionDataAccess { - private final Comparator versionComparator; + private final Comparator versionComparator; private final CacheKeysFactory keysFactory; public CollectionReadWriteAccess( @@ -61,7 +61,7 @@ public Object getCacheKeyId(Object cacheKey) { } @Override - protected Comparator getVersionComparator() { + protected Comparator getVersionComparator() { return versionComparator; } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/EntityReadWriteAccess.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/EntityReadWriteAccess.java index a1d36dee473b..d99edbac56de 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/EntityReadWriteAccess.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/EntityReadWriteAccess.java @@ -24,7 +24,7 @@ */ public class EntityReadWriteAccess extends AbstractReadWriteAccess implements EntityDataAccess { private final CacheKeysFactory keysFactory; - private final Comparator versionComparator; + private final Comparator versionComparator; public EntityReadWriteAccess( DomainDataRegion domainDataRegion, @@ -52,7 +52,7 @@ protected AccessedDataClassification getAccessedDataClassification() { } @Override - protected Comparator getVersionComparator() { + protected Comparator getVersionComparator() { return versionComparator; } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/NaturalIdReadWriteAccess.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/NaturalIdReadWriteAccess.java index 7856d162b71b..93fa2c02e62a 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/support/NaturalIdReadWriteAccess.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/support/NaturalIdReadWriteAccess.java @@ -44,7 +44,7 @@ public AccessType getAccessType() { } @Override - protected Comparator getVersionComparator() { + protected Comparator getVersionComparator() { // natural id has no comparator return null; }