Fix bug with creating a NaturalIdCacheKey via SimpleCacheKeysFactory
This commit is contained in:
parent
9fe3c861ca
commit
834426e8f6
|
@ -51,7 +51,7 @@ public class DefaultCacheKeysFactory implements CacheKeysFactory {
|
|||
}
|
||||
|
||||
public static Object staticCreateNaturalIdKey(Object naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||
return new NaturalIdCacheKey( naturalIdValues, persister.getPropertyTypes(), persister.getNaturalIdentifierProperties(), persister.getRootEntityName(), session );
|
||||
return new NaturalIdCacheKey( naturalIdValues, persister, session );
|
||||
}
|
||||
|
||||
public static Object staticGetEntityId(Object cacheKey) {
|
||||
|
|
|
@ -13,9 +13,8 @@ import java.util.Objects;
|
|||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* Defines a key for caching natural identifier resolutions into the second level cache.
|
||||
|
@ -34,24 +33,15 @@ public class NaturalIdCacheKey implements Serializable {
|
|||
// "transient" is important here -- NaturalIdCacheKey needs to be Serializable
|
||||
private transient ValueHolder<String> toString;
|
||||
|
||||
/**
|
||||
* Construct a new key for a caching natural identifier resolutions into the second level cache.
|
||||
* @param naturalIdValues The naturalIdValues associated with the cached data
|
||||
* @param propertyTypes
|
||||
* @param naturalIdPropertyIndexes
|
||||
* @param session The originating session
|
||||
*/
|
||||
public NaturalIdCacheKey(
|
||||
final Object naturalIdValues,
|
||||
Type[] propertyTypes,
|
||||
int[] naturalIdPropertyIndexes,
|
||||
final String entityName,
|
||||
final SharedSessionContractImplementor session) {
|
||||
public NaturalIdCacheKey(Object naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||
this( naturalIdValues, persister, persister.getRootEntityName(), session );
|
||||
}
|
||||
|
||||
public NaturalIdCacheKey(Object naturalIdValues, EntityPersister persister, String entityName, SharedSessionContractImplementor session) {
|
||||
this.entityName = entityName;
|
||||
this.tenantId = session.getTenantIdentifier();
|
||||
|
||||
final EntityMappingType entityMappingType = session.getFactory().getRuntimeMetamodels().getEntityMappingType( entityName );
|
||||
final NaturalIdMapping naturalIdMapping = entityMappingType.getNaturalIdMapping();
|
||||
final NaturalIdMapping naturalIdMapping = persister.getNaturalIdMapping();
|
||||
|
||||
this.naturalIdValues = naturalIdMapping.disassemble( naturalIdValues, session );
|
||||
this.hashCode = naturalIdMapping.calculateHashCode( naturalIdValues, session );
|
||||
|
@ -61,28 +51,24 @@ public class NaturalIdCacheKey implements Serializable {
|
|||
|
||||
private void initTransients() {
|
||||
this.toString = new ValueHolder<>(
|
||||
new ValueHolder.DeferredInitializer<String>() {
|
||||
@Override
|
||||
public String initialize() {
|
||||
//Complex toString is needed as naturalIds for entities are not simply based on a single value like primary keys
|
||||
//the only same way to differentiate the keys is to include the disassembled values in the string.
|
||||
final StringBuilder toStringBuilder = new StringBuilder()
|
||||
.append( entityName ).append( "##NaturalId[" );
|
||||
if ( naturalIdValues instanceof Object[] ) {
|
||||
final Object[] values = (Object[]) naturalIdValues;
|
||||
for ( int i = 0; i < values.length; i++ ) {
|
||||
toStringBuilder.append( values[ i ] );
|
||||
if ( i + 1 < values.length ) {
|
||||
toStringBuilder.append( ", " );
|
||||
}
|
||||
() -> {
|
||||
//Complex toString is needed as naturalIds for entities are not simply based on a single value like primary keys
|
||||
//the only same way to differentiate the keys is to include the disassembled values in the string.
|
||||
final StringBuilder toStringBuilder = new StringBuilder().append( entityName ).append( "##NaturalId[" );
|
||||
if ( naturalIdValues instanceof Object[] ) {
|
||||
final Object[] values = (Object[]) naturalIdValues;
|
||||
for ( int i = 0; i < values.length; i++ ) {
|
||||
toStringBuilder.append( values[ i ] );
|
||||
if ( i + 1 < values.length ) {
|
||||
toStringBuilder.append( ", " );
|
||||
}
|
||||
}
|
||||
else {
|
||||
toStringBuilder.append( naturalIdValues );
|
||||
}
|
||||
|
||||
return toStringBuilder.toString();
|
||||
}
|
||||
else {
|
||||
toStringBuilder.append( naturalIdValues );
|
||||
}
|
||||
|
||||
return toStringBuilder.toString();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class SimpleCacheKeysFactory implements CacheKeysFactory {
|
|||
@Override
|
||||
public Object createNaturalIdKey(Object naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||
// natural ids always need to be wrapped
|
||||
return new NaturalIdCacheKey(naturalIdValues, persister.getPropertyTypes(), persister.getNaturalIdentifierProperties(), null, session);
|
||||
return new NaturalIdCacheKey(naturalIdValues, persister, null, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.caching;
|
||||
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.internal.SimpleCacheKeysFactory;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
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.Test;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel( annotatedClasses = NaturalIdCacheKeyCreationTests.TheEntity.class )
|
||||
@SessionFactory
|
||||
public class NaturalIdCacheKeyCreationTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleKeyCreation(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
final EntityPersister entityDescriptor = (EntityPersister) session
|
||||
.getFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getEntityMappingType( TheEntity.class );
|
||||
|
||||
SimpleCacheKeysFactory.INSTANCE.createEntityKey( 1, entityDescriptor, session.getSessionFactory(), null );
|
||||
SimpleCacheKeysFactory.INSTANCE.createNaturalIdKey( "Steve", entityDescriptor, session );
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultKeyCreation(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
final EntityPersister entityDescriptor = (EntityPersister) session
|
||||
.getFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getEntityMappingType( TheEntity.class );
|
||||
|
||||
DefaultCacheKeysFactory.INSTANCE.createEntityKey( 1, entityDescriptor, session.getSessionFactory(), null );
|
||||
DefaultCacheKeysFactory.INSTANCE.createNaturalIdKey( "Steve", entityDescriptor, session );
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity( name = "TheEntity" )
|
||||
@Table( name = "`entities`" )
|
||||
public static class TheEntity {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Basic
|
||||
@NaturalId
|
||||
private String name;
|
||||
|
||||
private TheEntity() {
|
||||
// for use by Hibernate
|
||||
}
|
||||
|
||||
public TheEntity(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.internal.NaturalIdCacheKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -21,6 +22,11 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -30,6 +36,7 @@ import static org.mockito.Mockito.mock;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class NaturalIdCacheKeyTest {
|
||||
|
||||
@Test
|
||||
public void testSerializationRoundTrip() throws Exception {
|
||||
final SessionFactoryImplementor sessionFactoryImplementor = mock( SessionFactoryImplementor.class );
|
||||
|
@ -65,4 +72,10 @@ public class NaturalIdCacheKeyTest {
|
|||
assertEquals(key.getTenantId(), keyClone.getTenantId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimpleKeyCreation() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue