HHH-16281 Inconsistent Behaivor of L2 cache between Hibernate 5 and 6
This commit is contained in:
parent
52e95aec46
commit
c9640c2ee3
|
@ -56,7 +56,13 @@ public interface BasicValuedMapping extends ValueMapping, SqlExpressible {
|
|||
}
|
||||
|
||||
@Override
|
||||
default void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session){
|
||||
default void addToCacheKey(
|
||||
MutableCacheKeyBuilder cacheKey,
|
||||
Object value,
|
||||
SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
final JdbcMapping jdbcMapping = getJdbcMapping();
|
||||
final BasicValueConverter converter = jdbcMapping.getValueConverter();
|
||||
final Serializable disassemble;
|
||||
|
|
|
@ -320,6 +320,9 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
final Serializable[] result = new Serializable[ getNumberOfAttributeMappings() ];
|
||||
for ( int i = 0; i < result.length; i++ ) {
|
||||
final AttributeMapping attributeMapping = getAttributeMapping( i );
|
||||
|
|
|
@ -423,6 +423,9 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
final JdbcMapping jdbcMapping = getJdbcMapping();
|
||||
final BasicValueConverter converter = jdbcMapping.getValueConverter();
|
||||
final Serializable disassemble;
|
||||
|
|
|
@ -44,6 +44,9 @@ public class TupleMappingModelExpressible implements MappingModelExpressible {
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
for ( int i = 0; i < components.length; i++ ) {
|
||||
components[i].addToCacheKey( cacheKey, value, session );
|
||||
}
|
||||
|
|
|
@ -317,6 +317,9 @@ public class AnonymousTupleBasicValuedModelPart implements ModelPart, MappingTyp
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
cacheKey.addValue( value );
|
||||
cacheKey.addHashCode( ( (JavaType) getExpressibleJavaType() ).extractHashCode( value ) );
|
||||
}
|
||||
|
|
|
@ -123,6 +123,9 @@ public class JdbcLiteral<T> implements Literal, MappingModelExpressible<T>, Doma
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
final Serializable disassemble = ( (MutabilityPlan<Object>) jdbcMapping.getJdbcJavaType().getMutabilityPlan() )
|
||||
.disassemble( value, session );
|
||||
final int hashCode = jdbcMapping.getJavaTypeDescriptor().extractHashCode( value );
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.sql.exec.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
@ -158,20 +159,27 @@ public abstract class AbstractJdbcParameter
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
final JdbcMapping jdbcMapping = getJdbcMapping();
|
||||
final BasicValueConverter converter = jdbcMapping.getValueConverter();
|
||||
|
||||
final Serializable disassemble;
|
||||
final int hashCode;
|
||||
if ( converter == null ) {
|
||||
final JavaType javaTypeDescriptor = jdbcMapping.getJavaTypeDescriptor();
|
||||
cacheKey.addValue( javaTypeDescriptor.getMutabilityPlan().disassemble( value, session ) );
|
||||
cacheKey.addHashCode( javaTypeDescriptor.extractHashCode( value ) );
|
||||
disassemble = javaTypeDescriptor.getMutabilityPlan().disassemble( value, session );
|
||||
hashCode = javaTypeDescriptor.extractHashCode( value );
|
||||
}
|
||||
else {
|
||||
final Object relationalValue = converter.toRelationalValue( value );
|
||||
final JavaType relationalJavaType = converter.getRelationalJavaType();
|
||||
cacheKey.addValue( relationalJavaType.getMutabilityPlan().disassemble( relationalValue, session ) );
|
||||
cacheKey.addHashCode( relationalJavaType.extractHashCode( relationalValue ) );
|
||||
disassemble = relationalJavaType.getMutabilityPlan().disassemble( relationalValue, session );
|
||||
hashCode = relationalJavaType.extractHashCode( relationalValue );
|
||||
}
|
||||
cacheKey.addValue( disassemble );
|
||||
cacheKey.addHashCode( hashCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -220,6 +220,9 @@ public class CustomType<J>
|
|||
|
||||
@Override
|
||||
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return;
|
||||
}
|
||||
final Serializable disassembled = getUserType().disassemble( (J) value );
|
||||
// Since UserType#disassemble is an optional operation,
|
||||
// we have to handle the fact that it could produce a null value,
|
||||
|
|
|
@ -95,6 +95,44 @@ public class QueryCacheWithObjectParameterTest {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryWithEmbeddableParameterWithANull(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
evictQueryRegion( session );
|
||||
Query<Parent> queryParent = session.createQuery(
|
||||
"from Parent p where p.address = :address",
|
||||
Parent.class
|
||||
);
|
||||
queryParent.setParameter( "address", new Address( "via Milano", null ) );
|
||||
queryParent.setCacheable( true );
|
||||
|
||||
List<Parent> resultList = queryParent.getResultList();
|
||||
assertThat( resultList ).hasSize( 0 );
|
||||
|
||||
CacheRegionStatistics defaultQueryCacheRegionStatistics = getQueryCacheRegionStatistics( session );
|
||||
assertThat( defaultQueryCacheRegionStatistics.getHitCount() ).isEqualTo( 0 );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query<Parent> queryParent = session.createQuery(
|
||||
"from Parent p where p.address = :address",
|
||||
Parent.class
|
||||
);
|
||||
queryParent.setParameter( "address", new Address( "via Milano", null ) );
|
||||
queryParent.setCacheable( true );
|
||||
|
||||
List<Parent> resultList = queryParent.getResultList();
|
||||
assertThat( resultList ).hasSize( 0 );
|
||||
|
||||
CacheRegionStatistics defaultQueryCacheRegionStatistics = getQueryCacheRegionStatistics( session );
|
||||
assertThat( defaultQueryCacheRegionStatistics.getHitCount() ).isEqualTo( 1 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryCacheHits(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
|
@ -189,6 +227,56 @@ public class QueryCacheWithObjectParameterTest {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryCacheHitsNullParameter(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
evictQueryRegion( session );
|
||||
Query<Parent> queryParent = session.createQuery(
|
||||
"from Parent p where p.name = 'John'",
|
||||
Parent.class
|
||||
);
|
||||
List<Parent> p = queryParent.getResultList();
|
||||
assertThat( p ).hasSize( 1 );
|
||||
|
||||
Query<Child> queryChildren = session.createQuery(
|
||||
"from Child c where c.parent.id = ?1",
|
||||
Child.class
|
||||
);
|
||||
queryChildren.setParameter( 1, null );
|
||||
queryChildren.setCacheable( true );
|
||||
List<Child> c = queryChildren.getResultList();
|
||||
assertThat( c ).hasSize( 0 );
|
||||
|
||||
CacheRegionStatistics defaultQueryCacheRegionStatistics = getQueryCacheRegionStatistics( session );
|
||||
assertThat( defaultQueryCacheRegionStatistics.getHitCount() ).isEqualTo( 0 );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Query<Parent> queryParent = session.createQuery(
|
||||
"from Parent p where p.name = 'John'",
|
||||
Parent.class
|
||||
);
|
||||
List<Parent> p = queryParent.getResultList();
|
||||
assertThat( p ).hasSize( 1 );
|
||||
|
||||
Query<Child> queryChildren = session.createQuery(
|
||||
"from Child c where c.parent.id = ?1",
|
||||
Child.class
|
||||
);
|
||||
queryChildren.setParameter( 1, null );
|
||||
queryChildren.setCacheable( true );
|
||||
List<Child> c = queryChildren.getResultList();
|
||||
assertThat( c ).hasSize( 0 );
|
||||
|
||||
CacheRegionStatistics defaultQueryCacheRegionStatistics = getQueryCacheRegionStatistics( session );
|
||||
assertThat( defaultQueryCacheRegionStatistics.getHitCount() ).isEqualTo( 1 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static void evictQueryRegion(SessionImplementor session) {
|
||||
session.getSessionFactory()
|
||||
.getCache()
|
||||
|
|
Loading…
Reference in New Issue