Change `@ParamDef#type` associated with a `@FilterDef` from `String` to `Class` in keeping with the general move away from String-based type usage in annotations

This commit is contained in:
Steve Ebersole 2022-01-24 07:15:42 -06:00
parent 596317da0b
commit d6c4f90f4c
38 changed files with 308 additions and 255 deletions

View File

@ -112,7 +112,7 @@ public class FilterJoinTableTest extends BaseEntityManagerFunctionalTestCase {
name="firstAccounts",
parameters=@ParamDef(
name="maxOrderId",
type="int"
type=int.class
)
)
public static class Client {

View File

@ -104,7 +104,7 @@ public class FilterSqlFragementAliasTest extends BaseEntityManagerFunctionalTest
name="activeAccount",
parameters = @ParamDef(
name="active",
type="boolean"
type=Boolean.class
)
)
@Filter(

View File

@ -275,7 +275,7 @@ public class FilterTest extends BaseEntityManagerFunctionalTestCase {
name="activeAccount",
parameters = @ParamDef(
name="active",
type="boolean"
type=Boolean.class
)
)
@Filter(

View File

@ -12,20 +12,44 @@ import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* A parameter definition.
* Details about a parameter defined in a FilterDef.
* <p/>
* Mainly used to support cases where the proper {@link #type type}
* cannot be deduced by Hibernate.
*
* @see FilterDef#parameters()
*
* @author Steve Ebersole
* @author Emmanuel Bernard
*/
@Target({})
@Retention(RUNTIME)
public @interface ParamDef {
/**
* The name of the parameter definition.
* The name of the parameter.
*/
String name();
/**
* The type of the parameter.
* The type to use when binding the parameter value.
* <p/>
* Generally deduced from the bind value. Allows to
* specify a specific type to use.
* <p/>
* The supplied Class can be one of the following:<ul>
* <li>
* a {@link org.hibernate.usertype.UserType}
* </li>
* <li>
* an {@link jakarta.persistence.AttributeConverter}
* </li>
* <li>
* a {@link org.hibernate.type.descriptor.java.JavaType}
* </li>
* <li>
* any Java type resolvable from {@link org.hibernate.type.descriptor.java.spi.JavaTypeRegistry}
* </li>
* </ul>
*/
String type();
Class<?> type();
}

View File

@ -9,17 +9,18 @@ package org.hibernate.boot.model.source.internal.hbm;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import jakarta.xml.bind.JAXBElement;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmFilterDefinitionType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmFilterParameterType;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.jboss.logging.Logger;
import jakarta.xml.bind.JAXBElement;
/**
* @author Steve Ebersole
*/
@ -36,7 +37,7 @@ class FilterDefinitionBinder {
static void processFilterDefinition(
HbmLocalMetadataBuildingContext context,
JaxbHbmFilterDefinitionType jaxbFilterDefinitionMapping) {
Map<String,Type> parameterMap = null;
Map<String, JdbcMapping> parameterMap = null;
String condition = jaxbFilterDefinitionMapping.getCondition();
for ( Serializable content : jaxbFilterDefinitionMapping.getContent() ) {

View File

@ -58,26 +58,4 @@ public final class FilterKey implements Serializable {
return "FilterKey[" + filterName + filterParameters + ']';
}
/**
* Constructs a number of FilterKey instances, given the currently enabled filters
*
* @param enabledFilters The currently enabled filters
*
* @return The filter keys, one per enabled filter
*/
public static Set<FilterKey> createFilterKeys(Map<String,Filter> enabledFilters) {
if ( enabledFilters.size() == 0 ) {
return null;
}
final Set<FilterKey> result = new HashSet<>();
for ( Filter filter : enabledFilters.values() ) {
final FilterKey key = new FilterKey(
filter.getName(),
( (FilterImpl) filter ).getParameters(),
filter.getFilterDefinition().getParameterTypes()
);
result.add( key );
}
return result;
}
}

View File

@ -39,6 +39,7 @@ import org.hibernate.annotations.CollectionTypeRegistration;
import org.hibernate.annotations.CollectionTypeRegistrations;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.DialectOverride;
import org.hibernate.annotations.DialectOverride.OverridesAnnotation;
import org.hibernate.annotations.DiscriminatorFormula;
import org.hibernate.annotations.DiscriminatorOptions;
@ -51,7 +52,6 @@ import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.Filters;
import org.hibernate.annotations.DialectOverride;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.GenericGenerator;
@ -94,6 +94,7 @@ import org.hibernate.annotations.common.reflection.XPackage;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.InFlightMetadataCollector.EntityTableXref;
@ -108,6 +109,7 @@ import org.hibernate.cfg.annotations.Nullability;
import org.hibernate.cfg.annotations.PropertyBinder;
import org.hibernate.cfg.annotations.QueryBinder;
import org.hibernate.cfg.annotations.TableBinder;
import org.hibernate.cfg.internal.ConvertedJdbcMapping;
import org.hibernate.cfg.internal.NullableDiscriminatorColumnSecondPass;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.OptimisticLockStyle;
@ -137,10 +139,18 @@ import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.UnionSubclass;
import org.hibernate.metamodel.EmbeddableInstantiator;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.CustomType;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserType;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.AttributeOverrides;
import jakarta.persistence.Basic;
@ -1506,22 +1516,98 @@ public final class AnnotationBinder {
}
private static void bindFilterDef(FilterDef defAnn, MetadataBuildingContext context) {
Map<String, org.hibernate.type.Type> params = new HashMap<>();
for ( ParamDef param : defAnn.parameters() ) {
params.put(
param.name(),
context.getMetadataCollector()
.getTypeConfiguration()
.getBasicTypeRegistry()
.getRegisteredType( param.type() )
);
final Map<String, JdbcMapping> explicitParamJaMappings;
if ( defAnn.parameters().length == 0 ) {
explicitParamJaMappings = null;
}
else {
explicitParamJaMappings = new HashMap<>();
}
final FilterDefinition def = new FilterDefinition( defAnn.name(), defAnn.defaultCondition(), params );
for ( ParamDef param : defAnn.parameters() ) {
final JdbcMapping jdbcMapping = resolveFilterParamType( param.type(), context );
if ( jdbcMapping == null ) {
throw new MappingException(
String.format(
Locale.ROOT,
"Unable to resolve type specified for parameter (%s) defined for @FilterDef (%s)",
param.name(),
defAnn.name()
)
);
}
explicitParamJaMappings.put( param.name(), jdbcMapping );
}
final FilterDefinition def = new FilterDefinition( defAnn.name(), defAnn.defaultCondition(), explicitParamJaMappings );
LOG.debugf( "Binding filter definition: %s", def.getFilterName() );
context.getMetadataCollector().addFilterDefinition( def );
}
private static JdbcMapping resolveFilterParamType(Class<?> type, MetadataBuildingContext context) {
if ( UserType.class.isAssignableFrom( type ) ) {
return resolveUserType( (Class<UserType<?>>) type, context );
}
if ( AttributeConverter.class.isAssignableFrom( type ) ) {
return resolveAttributeConverter( (Class<AttributeConverter<?,?>>) type, context );
}
if ( JavaType.class.isAssignableFrom( type ) ) {
return resolveJavaType( (Class<JavaType<?>>) type, context );
}
final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration();
final JavaType<Object> jtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( type );
if ( jtd != null ) {
final JdbcType jdbcType = jtd.getRecommendedJdbcType( typeConfiguration.getCurrentBaseSqlTypeIndicators() );
return typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType );
}
return null;
}
private static JdbcMapping resolveUserType(Class<UserType<?>> type, MetadataBuildingContext context) {
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<UserType<?>> bean = beanRegistry.getBean( type );
final UserType<?> userType = bean.getBeanInstance();
//noinspection rawtypes
return new CustomType( userType, context.getBootstrapContext().getTypeConfiguration() );
}
private static JdbcMapping resolveAttributeConverter(Class<AttributeConverter<?, ?>> type, MetadataBuildingContext context) {
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<AttributeConverter<?, ?>> bean = beanRegistry.getBean( type );
return new ConvertedJdbcMapping<>( bean, context.getBootstrapContext().getTypeConfiguration() );
}
private static JdbcMapping resolveJavaType(Class<JavaType<?>> type, MetadataBuildingContext context) {
final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration();
final JavaTypeRegistry javaTypeRegistry = typeConfiguration.getJavaTypeRegistry();
final JavaType<?> registeredJtd = javaTypeRegistry.findDescriptor( type );
final JavaType<?> jtd;
if ( registeredJtd != null ) {
jtd = registeredJtd;
}
else {
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<JavaType<?>> bean = beanRegistry.getBean( type );
jtd = bean.getBeanInstance();
}
final JdbcType jdbcType = jtd.getRecommendedJdbcType( typeConfiguration.getCurrentBaseSqlTypeIndicators() );
return typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType );
}
private static void bindCallbacks(XClass entityClass, PersistentClass persistentClass,
MetadataBuildingContext context) {
ReflectionManager reflectionManager = context.getBootstrapContext().getReflectionManager();

View File

@ -0,0 +1,86 @@
/*
* 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.cfg.internal;
import java.lang.reflect.ParameterizedType;
import org.hibernate.internal.util.GenericsHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.converter.AttributeConverterJdbcTypeAdapter;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.AttributeConverter;
/**
* Ad-hoc JdbcMapping implementation for cases where we only have a converter
*
* @author Steve Ebersole
*/
public class ConvertedJdbcMapping<T> implements JdbcMapping {
private final ManagedBean<AttributeConverter<?, ?>> converterBean;
private final JavaType<T> domainJtd;
private final JavaType<?> relationalJtd;
private final JdbcType jdbcType;
@SuppressWarnings({ "unchecked", "rawtypes" })
public ConvertedJdbcMapping(
ManagedBean<AttributeConverter<?, ?>> converterBean,
TypeConfiguration typeConfiguration) {
this.converterBean = converterBean;
final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeRegistry();
final JavaType<? extends AttributeConverter<?,?>> converterJtd = jtdRegistry.resolveDescriptor( converterBean.getBeanClass() );
final ParameterizedType converterParameterizedType = GenericsHelper.extractParameterizedType( converterBean.getBeanClass() );
final Class<?> domainJavaClass = GenericsHelper.extractClass( converterParameterizedType.getActualTypeArguments()[0] );
final Class<?> relationalJavaClass = GenericsHelper.extractClass( converterParameterizedType.getActualTypeArguments()[1] );
this.domainJtd = jtdRegistry.resolveDescriptor( domainJavaClass );
this.relationalJtd = jtdRegistry.resolveDescriptor( relationalJavaClass );
final JpaAttributeConverterImpl converterDescriptor = new JpaAttributeConverterImpl(
converterBean,
converterJtd,
domainJtd,
relationalJtd
);
this.jdbcType = new AttributeConverterJdbcTypeAdapter(
converterDescriptor,
relationalJtd.getRecommendedJdbcType( typeConfiguration.getCurrentBaseSqlTypeIndicators() ),
relationalJtd
);
}
@Override
public JavaType<T> getJavaTypeDescriptor() {
return domainJtd;
}
@Override
public JdbcType getJdbcType() {
return jdbcType;
}
@Override
public ValueExtractor<?> getJdbcValueExtractor() {
return jdbcType.getExtractor( domainJtd );
}
@Override
public ValueBinder<T> getJdbcValueBinder() {
return jdbcType.getBinder( domainJtd );
}
}

View File

@ -11,7 +11,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.hibernate.type.Type;
import org.hibernate.metamodel.mapping.JdbcMapping;
/**
* Represents the definition of a {@link org.hibernate.Filter filter}.
@ -28,18 +28,18 @@ import org.hibernate.type.Type;
public class FilterDefinition implements Serializable {
private final String filterName;
private final String defaultFilterCondition;
private final Map<String, Type> parameterTypes = new HashMap<>();
private final Map<String, JdbcMapping> explicitParamJaMappings = new HashMap<>();
/**
* Construct a new FilterDefinition instance.
*
* @param name The name of the filter for which this configuration is in effect.
*/
public FilterDefinition(String name, String defaultCondition, Map<String, Type> parameterTypes) {
public FilterDefinition(String name, String defaultCondition, Map<String, JdbcMapping> explicitParamJaMappings) {
this.filterName = name;
this.defaultFilterCondition = defaultCondition;
if ( parameterTypes != null ) {
this.parameterTypes.putAll( parameterTypes );
if ( explicitParamJaMappings != null ) {
this.explicitParamJaMappings.putAll( explicitParamJaMappings );
}
}
@ -58,7 +58,7 @@ public class FilterDefinition implements Serializable {
* @return The parameters named by this configuration.
*/
public Set<String> getParameterNames() {
return parameterTypes.keySet();
return explicitParamJaMappings.keySet();
}
/**
@ -68,16 +68,12 @@ public class FilterDefinition implements Serializable {
*
* @return The type of the named parameter.
*/
public Type getParameterType(String parameterName) {
return parameterTypes.get( parameterName );
public JdbcMapping getParameterJdbcMapping(String parameterName) {
return explicitParamJaMappings.get( parameterName );
}
public String getDefaultFilterCondition() {
return defaultFilterCondition;
}
public Map<String, Type> getParameterTypes() {
return parameterTypes;
}
}

View File

@ -11,18 +11,14 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;
import jakarta.persistence.EntityGraph;
import org.hibernate.Filter;
import org.hibernate.UnknownProfileException;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.FilterImpl;
import org.hibernate.loader.ast.spi.CascadingFetchProfile;
import org.hibernate.type.Type;
/**
* Centralize all options which can influence the SQL query needed to load an
@ -76,13 +72,6 @@ public class LoadQueryInfluencers implements Serializable {
// internal fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void withInternalFetchProfile(CascadingFetchProfile profile, InternalFetchProfileAction action) {
final CascadingFetchProfile previous = this.enabledCascadingFetchProfile;
this.enabledCascadingFetchProfile = profile;
action.performAction();
this.enabledCascadingFetchProfile = previous;
}
public <T> T fromInternalFetchProfile(CascadingFetchProfile profile, Supplier<T> supplier) {
final CascadingFetchProfile previous = this.enabledCascadingFetchProfile;
this.enabledCascadingFetchProfile = profile;
@ -94,11 +83,6 @@ public class LoadQueryInfluencers implements Serializable {
}
}
@FunctionalInterface
public interface InternalFetchProfileAction {
void performAction();
}
public CascadingFetchProfile getEnabledCascadingFetchProfile() {
return enabledCascadingFetchProfile;
}
@ -116,7 +100,7 @@ public class LoadQueryInfluencers implements Serializable {
/**
* @deprecated Use {@link #getEnabledCascadingFetchProfile} instead
*/
@Deprecated
@Deprecated( since = "6.0" )
public String getInternalFetchProfile() {
return getEnabledCascadingFetchProfile().getLegacyName();
}
@ -124,7 +108,7 @@ public class LoadQueryInfluencers implements Serializable {
/**
* @deprecated Use {@link #setEnabledCascadingFetchProfile} instead
*/
@Deprecated
@Deprecated( since = "6.0" )
public void setInternalFetchProfile(String internalFetchProfile) {
setEnabledCascadingFetchProfile( CascadingFetchProfile.fromLegacyName( internalFetchProfile ) );
}
@ -138,7 +122,7 @@ public class LoadQueryInfluencers implements Serializable {
public Map<String,Filter> getEnabledFilters() {
if ( enabledFilters == null ) {
return Collections.EMPTY_MAP;
return Collections.emptyMap();
}
else {
// First, validate all the enabled filters...
@ -156,7 +140,7 @@ public class LoadQueryInfluencers implements Serializable {
*/
public Set<String> getEnabledFilterNames() {
if ( enabledFilters == null ) {
return Collections.EMPTY_SET;
return Collections.emptySet();
}
else {
return Collections.unmodifiableSet( enabledFilters.keySet() );
@ -199,20 +183,6 @@ public class LoadQueryInfluencers implements Serializable {
return filter.getParameter( parsed[1] );
}
public Type getFilterParameterType(String filterParameterName) {
final String[] parsed = parseFilterParameterName( filterParameterName );
final FilterDefinition filterDef = sessionFactory.getFilterDefinition( parsed[0] );
if ( filterDef == null ) {
throw new IllegalArgumentException( "Filter [" + parsed[0] + "] not defined" );
}
final Type type = filterDef.getParameterType( parsed[1] );
if ( type == null ) {
// this is an internal error of some sort...
throw new InternalError( "Unable to locate type for filter parameter" );
}
return type;
}
public static String[] parseFilterParameterName(String filterParameterName) {
int dot = filterParameterName.lastIndexOf( '.' );
if ( dot <= 0 ) {
@ -233,12 +203,7 @@ public class LoadQueryInfluencers implements Serializable {
}
public Set<String> getEnabledFetchProfileNames() {
if ( enabledFetchProfileNames == null ) {
return Collections.EMPTY_SET;
}
else {
return enabledFetchProfileNames;
}
return Objects.requireNonNullElse( enabledFetchProfileNames, Collections.emptySet() );
}
private void checkFetchProfileName(String name) {
@ -271,66 +236,6 @@ public class LoadQueryInfluencers implements Serializable {
return effectiveEntityGraph;
}
/**
* @deprecated (since 5.4) {@link #getFetchGraph}, {@link #getLoadGraph}, {@link #setFetchGraph}
* and {@link #setLoadGraph} (as well as JPA itself honestly) all make it very unclear that
* there can be only one graph applied at any one time and that graph is *either* a load or
* a fetch graph. These have all been replaced with {@link #getEffectiveEntityGraph()}.
*
* @see EffectiveEntityGraph
*/
@Deprecated
public EntityGraph getFetchGraph() {
if ( effectiveEntityGraph.getSemantic() != GraphSemantic.FETCH ) {
return null;
}
return effectiveEntityGraph.getGraph();
}
/**
* @deprecated (since 5.4) {@link #getFetchGraph}, {@link #getLoadGraph}, {@link #setFetchGraph}
* and {@link #setLoadGraph} (as well as JPA itself honestly) all make it very unclear that
* there can be only one graph applied at any one time and that graph is *either* a load or
* a fetch graph. These have all been replaced with {@link #getEffectiveEntityGraph()}.
*
* @see EffectiveEntityGraph
*/
@Deprecated
public void setFetchGraph(EntityGraph fetchGraph) {
effectiveEntityGraph.applyGraph( (RootGraphImplementor<?>) fetchGraph, GraphSemantic.FETCH );
}
/**
* @deprecated (since 5.4) {@link #getFetchGraph}, {@link #getLoadGraph}, {@link #setFetchGraph}
* and {@link #setLoadGraph} (as well as JPA itself honestly) all make it very unclear that
* there can be only one graph applied at any one time and that graph is *either* a load or
* a fetch graph. These have all been replaced with {@link #getEffectiveEntityGraph()}.
*
* @see EffectiveEntityGraph
*/
@Deprecated
public EntityGraph getLoadGraph() {
if ( effectiveEntityGraph.getSemantic() != GraphSemantic.LOAD ) {
return null;
}
return effectiveEntityGraph.getGraph();
}
/**
* @deprecated (since 5.4) {@link #getFetchGraph}, {@link #getLoadGraph}, {@link #setFetchGraph}
* and {@link #setLoadGraph} (as well as JPA itself honestly) all make it very unclear that
* there can be only one graph applied at any one time and that that graph is *either* a load or
* a fetch graph. These have all been replaced with {@link #getEffectiveEntityGraph()}.
*
* @see EffectiveEntityGraph
*/
@Deprecated
public void setLoadGraph(final EntityGraph loadGraph) {
effectiveEntityGraph.applyGraph( (RootGraphImplementor<?>) loadGraph, GraphSemantic.LOAD );
}
public Boolean getReadOnly() {
return readOnly;
}

View File

@ -27,7 +27,6 @@ import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.type.Type;
import static org.hibernate.internal.util.StringHelper.safeInterning;
@ -167,12 +166,9 @@ public class FilterHelper {
if ( CollectionHelper.isNotEmpty( filterParameterNames ) ) {
for ( int paramPos = 0; paramPos < filterParameterNames.size(); paramPos++ ) {
final String parameterName = filterParameterNames.get( paramPos );
final Type parameterType = enabledFilter.getFilterDefinition().getParameterType( parameterName );
if ( ! (parameterType instanceof JdbcMapping) ) {
throw new MappingException( String.format( "parameter [%s] for filter [%s] is not of JdbcMapping type", parameterName, filterName ) );
}
final JdbcMapping jdbcMapping = (JdbcMapping) parameterType;
final JdbcMapping jdbcMapping = enabledFilter
.getFilterDefinition()
.getParameterJdbcMapping( parameterName );
final Object parameterValue = enabledFilter.getParameter( parameterName );
if ( parameterValue == null ) {
throw new MappingException( String.format( "unknown parameter [%s] for filter [%s]", parameterName, filterName ) );

View File

@ -16,8 +16,7 @@ import org.hibernate.Filter;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
import org.hibernate.metamodel.mapping.JdbcMapping;
/**
* Implementation of FilterImpl. FilterImpl implements the user's
@ -75,7 +74,7 @@ public class FilterImpl implements Filter, Serializable {
*/
public Filter setParameter(String name, Object value) throws IllegalArgumentException {
// Make sure this is a defined parameter and check the incoming value type
BasicType<?> type = (BasicType<?>) definition.getParameterType( name );
JdbcMapping type = definition.getParameterJdbcMapping( name );
if ( type == null ) {
throw new IllegalArgumentException( "Undefined filter parameter [" + name + "]" );
}
@ -99,13 +98,13 @@ public class FilterImpl implements Filter, Serializable {
if ( values == null ) {
throw new IllegalArgumentException( "Collection must be not null!" );
}
Type type = definition.getParameterType( name );
JdbcMapping type = definition.getParameterJdbcMapping( name );
if ( type == null ) {
throw new HibernateException( "Undefined filter parameter [" + name + "]" );
}
if ( !values.isEmpty() ) {
Class<?> elementClass = values.iterator().next().getClass();
if ( !type.getReturnedClass().isAssignableFrom( elementClass ) ) {
final Object element = values.iterator().next();
if ( !type.getJavaTypeDescriptor().isInstance( element ) ) {
throw new HibernateException( "Incorrect type for parameter [" + name + "]" );
}
}

View File

@ -16,6 +16,7 @@ import java.util.List;
import jakarta.persistence.AttributeConverter;
public class GenericsHelper {
public static ParameterizedType extractParameterizedType(Type base) {
if ( base == null ) {
return null;

View File

@ -1,27 +0,0 @@
/*
* 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.internal.util;
/**
* @author Steve Ebersole
*/
public class JavaHelper {
public static Package getPackageFor(String name) {
return getPackageFor( name, JavaHelper.class.getClassLoader() );
}
public static Package getPackageFor(String name, ClassLoader classLoader) {
// after Java 9 we can do -
//return classLoader.getDefinedPackage( name );
return Package.getPackage( name );
}
private JavaHelper() {
// disallow direct instantiation
}
}

View File

@ -11,13 +11,15 @@ import org.hibernate.annotations.TenantId;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
@ -38,11 +40,15 @@ public class TenantIdBinder implements AttributeBinder<TenantId> {
MetadataBuildingContext buildingContext,
PersistentClass persistentClass,
Property property) {
InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
BasicType<Object> tenantIdType =
collector.getTypeConfiguration().getBasicTypeRegistry()
.getRegisteredType( property.getReturnedClassName() );
FilterDefinition filterDefinition = collector.getFilterDefinition(FILTER_NAME);
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
final TypeConfiguration typeConfiguration = collector.getTypeConfiguration();
final String returnedClassName = property.getReturnedClassName();
final BasicType<Object> tenantIdType = typeConfiguration
.getBasicTypeRegistry()
.getRegisteredType( returnedClassName );
final FilterDefinition filterDefinition = collector.getFilterDefinition( FILTER_NAME );
if ( filterDefinition == null ) {
collector.addFilterDefinition(
new FilterDefinition(
@ -53,13 +59,16 @@ public class TenantIdBinder implements AttributeBinder<TenantId> {
);
}
else {
Type parameterType = filterDefinition.getParameterTypes().get(PARAMETER_NAME);
if ( !parameterType.getName().equals( tenantIdType.getName() ) ) {
final JavaType<?> tenantIdTypeJtd = tenantIdType.getJavaTypeDescriptor();
final JavaType<?> parameterJtd = filterDefinition
.getParameterJdbcMapping( PARAMETER_NAME )
.getJavaTypeDescriptor();
if ( !parameterJtd.getJavaTypeClass().equals( tenantIdTypeJtd.getJavaTypeClass() ) ) {
throw new MappingException(
"all @TenantId fields must have the same type: "
+ parameterType.getName()
+ parameterJtd.getJavaType().getTypeName()
+ " differs from "
+ tenantIdType.getName()
+ tenantIdTypeJtd.getJavaType().getTypeName()
);
}
}

View File

@ -23,7 +23,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.jboss.logging.Logger;
/**
* Adapter for incorporating JPA {@link AttributeConverter} handling into the SqlTypeDescriptor contract.
* Adapter for incorporating JPA {@link AttributeConverter} handling into the JdbcType contract.
* <p/>
* Essentially this is responsible for mapping to/from the intermediate database type representation. Continuing the
* {@code AttributeConverter<Integer,String>} example from

View File

@ -20,7 +20,7 @@ import org.hibernate.annotations.ParamDef;
* @author Emmanuel Bernard
*/
@Entity
@FilterDef(name="selectedLocale", parameters={ @ParamDef( name="param", type="string" ) } )
@FilterDef(name="selectedLocale", parameters={ @ParamDef( name="param", type=String.class ) } )
public class TestCourse {
private Long testCourseId;

View File

@ -46,7 +46,7 @@ import jakarta.persistence.Lob;
@OptimisticLocking(type = OptimisticLockType.ALL)
@Polymorphism(type = PolymorphismType.EXPLICIT)
@Where(clause = "1=1")
@FilterDef(name = "minLength", parameters = {@ParamDef(name = "minLength", type = "integer")})
@FilterDef(name = "minLength", parameters = {@ParamDef(name = "minLength", type = Integer.class)})
@Filter(name = "betweenLength")
@Filter(name = "minLength", condition = ":minLength <= length")
@org.hibernate.annotations.Table(appliesTo = "Forest",

View File

@ -17,7 +17,7 @@ import org.hibernate.annotations.ParamDef;
/**
* @author Sharath Reddy
*/
@FilterDef(name = "byCategory", parameters = {@ParamDef(name = "category", type = "string")})
@FilterDef(name = "byCategory", parameters = {@ParamDef(name = "category", type = String.class)})
@Filter(name = "byCategory", condition = ":category = `CATEGORY`")
@MappedSuperclass
public class Tool extends Widget {

View File

@ -22,7 +22,7 @@ import org.hibernate.annotations.ParamDef;
* @author Sharath Reddy
*/
@FilterDef(name="byState", defaultCondition=":state = state",
parameters=@ParamDef(name="state",type="string"))
parameters=@ParamDef(name="state",type=String.class))
@Entity
public class Topic {

View File

@ -15,7 +15,7 @@ import org.hibernate.annotations.ParamDef;
/**
* @author Sharath Reddy
*/
@FilterDef(name = "byName", parameters = {@ParamDef(name = "name", type = "string")})
@FilterDef(name = "byName", parameters = {@ParamDef(name = "name", type = String.class)})
@Filter(name = "byName", condition = ":name = name")
@MappedSuperclass
public class Widget {

View File

@ -13,8 +13,8 @@
name = "betweenLength",
defaultCondition = ":minLength <= length and :maxLength >= length",
parameters = {
@ParamDef(name = "minLength", type = "integer"),
@ParamDef(name = "maxLength", type = "integer")
@ParamDef(name = "minLength", type = Integer.class),
@ParamDef(name = "maxLength", type = Integer.class)
}
) package org.hibernate.orm.test.annotations.entity;

View File

@ -243,7 +243,7 @@ public class CriteriaQueryWithAppliedFilterTest {
name = "statusFilter",
parameters = {
@ParamDef(
name = "status", type = "string"
name = "status", type = String.class
)
}
)

View File

@ -9,12 +9,6 @@ package org.hibernate.orm.test.filter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
@ -26,13 +20,18 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.transaction.TransactionUtil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
@ -117,10 +116,10 @@ public class FilterDotNameTest {
@Entity(name = "PurchaseOrder")
@FilterDefs({
@FilterDef(name = "customerIdFilter", parameters = @ParamDef(name = "customerId", type = "long")),
@FilterDef(name = "PurchaseOrder.customerIdFilter", parameters = @ParamDef(name = "customerId", type = "long")),
@FilterDef(name = "itemIdFilter", parameters = @ParamDef(name = "itemId", type = "long")),
@FilterDef(name = "PurchaseOrder.itemIdFilter", parameters = @ParamDef(name = "itemId", type = "long"))
@FilterDef(name = "customerIdFilter", parameters = @ParamDef(name = "customerId", type = Long.class)),
@FilterDef(name = "PurchaseOrder.customerIdFilter", parameters = @ParamDef(name = "customerId", type = Long.class)),
@FilterDef(name = "itemIdFilter", parameters = @ParamDef(name = "itemId", type = Long.class)),
@FilterDef(name = "PurchaseOrder.itemIdFilter", parameters = @ParamDef(name = "itemId", type = Long.class))
})
@Filters({
@Filter(name = "customerIdFilter", condition = "customerId = :customerId"),

View File

@ -9,13 +9,6 @@ package org.hibernate.orm.test.filter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
@ -28,7 +21,6 @@ import org.hibernate.stat.Statistics;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@ -37,9 +29,16 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
/**
@ -127,7 +126,7 @@ public class FilterWitSubSelectFetchModeTest {
name = "ID",
defaultCondition = "customerId >= :id",
parameters = {
@ParamDef(type = "long", name = "id")
@ParamDef(type = Long.class, name = "id")
}
)
@Filter(name = "ID")

View File

@ -27,6 +27,7 @@ import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.Filters;
import org.hibernate.annotations.ParamDef;
import org.hibernate.query.Query;
import org.hibernate.type.YesNoConverter;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@ -100,8 +101,8 @@ public class OneToManyWithDynamicFilterTest {
@FilterDef(
name = "aliveOnly",
parameters = {
@ParamDef(name = "aliveTimestamp", type = "timestamp"),
@ParamDef(name = "deleted", type = "boolean")
@ParamDef(name = "aliveTimestamp", type = Timestamp.class),
@ParamDef(name = "deleted", type = YesNoConverter.class)
},
defaultCondition = "DELETION_TIMESTAMP = :aliveTimestamp and DELETED = :deleted")
})

View File

@ -74,7 +74,7 @@ public class BasicFilteredBulkManipulationTest {
name = "sex",
parameters = @ParamDef(
name= "sexCode",
type = "char"
type = Character.class
)
)
@Filter( name = "sex", condition = "SEX_CODE = :sexCode" )

View File

@ -127,7 +127,7 @@ public class JoinedFilteredBulkManipulationTest {
name = "sex",
parameters = @ParamDef(
name= "sexCode",
type = "char"
type = Character.class
)
)
@Filter( name = "sex", condition = "SEX_CODE = :sexCode" )

View File

@ -20,7 +20,7 @@ import org.hibernate.annotations.ParamDef;
* @author Steve Ebersole
*/
@Entity
@FilterDef( name="byRegion", parameters = {@ParamDef(name = "region", type = "string")})
@FilterDef( name="byRegion", parameters = {@ParamDef(name = "region", type = String.class)})
@Filter( name = "byRegion", condition = "region_cd = :region" )
public class Account {
private Long id;

View File

@ -23,8 +23,8 @@ import jakarta.persistence.Table;
@Entity
@Table(name="T_USER")
@SecondaryTable(name="SECURITY_USER")
@FilterDef(name="ageFilter", parameters=@ParamDef(name="age", type="integer"))
@Filter(name="ageFilter", condition="{u}.AGE < :age AND {s}.LOCKED_OUT <> 1",
@FilterDef(name="ageFilter", parameters=@ParamDef(name="age", type=Integer.class))
@Filter(name="ageFilter", condition="{u}.AGE < :age AND {s}.LOCKED_OUT <> 1",
aliases={@SqlFragmentAlias(alias="u", table="T_USER"), @SqlFragmentAlias(alias="s", table="SECURITY_USER")})
public class User {

View File

@ -16,7 +16,7 @@ import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
@MappedSuperclass
@FilterDef(name = "nameFilter", parameters = @ParamDef(name = "name", type = "string"))
@FilterDef(name = "nameFilter", parameters = @ParamDef(name = "name", type = String.class))
@Filter(name = "nameFilter", condition = ":name = ANIMAL_NAME")
public abstract class Animal {
@Id

View File

@ -21,7 +21,7 @@ import org.hibernate.annotations.ParamDef;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@Table(name="ZOOLOGY_ANIMAL")
@FilterDef(name="ignoreSome", parameters={@ParamDef(name="name", type="string")})
@FilterDef(name="ignoreSome", parameters={@ParamDef(name="name", type=String.class)})
@Filter(name="ignoreSome", condition=":name <> ANIMAL_NAME")
public class Animal {
@Id

View File

@ -20,7 +20,7 @@ import org.hibernate.annotations.ParamDef;
import org.hibernate.annotations.SqlFragmentAlias;
@Entity
@FilterDef(name="iqMin", parameters={@ParamDef(name="min", type="integer")})
@FilterDef(name="iqMin", parameters={@ParamDef(name="min", type=Integer.class)})
@FilterDef(name="pregnantMembers")
public class Club {
@Id

View File

@ -19,8 +19,8 @@ import org.hibernate.annotations.ParamDef;
@Table(name="ZOOLOGY_HUMAN")
@FilterDef(name="iqRange", parameters=
{
@ParamDef(name="min", type="integer"),
@ParamDef(name="max", type="integer")
@ParamDef(name="min", type=Integer.class),
@ParamDef(name="max", type=Integer.class)
})
@Filter(name="iqRange", condition="HUMAN_IQ BETWEEN :min AND :max")
public class Human extends Mammal {

View File

@ -21,7 +21,7 @@ import org.hibernate.annotations.ParamDef;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name="ZOOLOGY_ANIMAL")
@FilterDef(name="ignoreSome", parameters={@ParamDef(name="name", type="string")})
@FilterDef(name="ignoreSome", parameters={@ParamDef(name="name", type=String.class)})
@Filter(name="ignoreSome", deduceAliasInjectionPoints=false, condition=":name <> {alias}.ANIMAL_NAME")
public class Animal {
@Id

View File

@ -18,8 +18,8 @@ import org.hibernate.annotations.ParamDef;
@Table(name="ZOOLOGY_HUMAN")
@FilterDef(name="iqRange", parameters=
{
@ParamDef(name="min", type="integer"),
@ParamDef(name="max", type="integer")
@ParamDef(name="min", type=Integer.class),
@ParamDef(name="max", type=Integer.class)
})
@Filter(name="iqRange", condition="HUMAN_IQ BETWEEN :min AND :max")
public class Human extends Mammal {

View File

@ -21,7 +21,7 @@ import org.hibernate.annotations.ParamDef;
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@Table(name="ZOOLOGY_ANIMAL")
@FilterDef(name="ignoreSome", parameters={@ParamDef(name="name", type="string")})
@FilterDef(name="ignoreSome", parameters={@ParamDef(name="name", type=String.class)})
@Filter(name="ignoreSome", condition=":name <> ANIMAL_NAME")
public class Animal {
@Id

View File

@ -18,8 +18,8 @@ import org.hibernate.annotations.ParamDef;
@Table(name="ZOOLOGY_HUMAN")
@FilterDef(name="iqRange", parameters=
{
@ParamDef(name="min", type="integer"),
@ParamDef(name="max", type="integer")
@ParamDef(name="min", type=Integer.class),
@ParamDef(name="max", type=Integer.class)
})
@Filter(name="iqRange", condition="HUMAN_IQ BETWEEN :min AND :max")
public class Human extends Mammal {