improvements to filter-related javadoc

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-06-12 13:12:55 +02:00
parent 52f9ce3c0e
commit 58e814965e
5 changed files with 64 additions and 27 deletions

View File

@ -13,12 +13,21 @@ import org.hibernate.annotations.FilterDef;
import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
/** /**
* Exception thrown if a filter would make a to-one association {@code null}, * Thrown if an enabled {@linkplain FilterDef filter} would filter out
* which could lead to data loss. * the target of a {@link jakarta.persistence.ManyToOne @ManyToOne} or
* Even though filters are applied to load-by-key operations, * {@link jakarta.persistence.OneToOne @OneToOne} association.
* a to-one association should never refer to an entity that is filtered. * <p>
* By default, a filter does not apply to to-one association fetching,
* and this exception does not occur. However, if a filter is explicitly
* declared {@link FilterDef#applyToLoadByKey applyToLoadByKey = true},
* then the filter is applied, and it's possible that a filtered entity
* is the target of a to-one association belonging to an unfiltered entity.
* Replacing such a filtered object with {@code null} would lead to data
* loss, and so filtering never results in such replacement. Instead,
* this exception is thrown to indicate the inconsistency of the data
* with the filter definition.
* *
* @see FilterDef#applyToLoadByKey() * @see FilterDef#applyToLoadByKey
*/ */
public class EntityFilterException extends EntityNotFoundException { public class EntityFilterException extends EntityNotFoundException {
private final String entityName; private final String entityName;

View File

@ -8,18 +8,24 @@ package org.hibernate;
import java.util.Collection; import java.util.Collection;
import org.hibernate.annotations.FilterDef;
import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.FilterDefinition;
/** /**
* Allows control over an enabled filter at runtime. In particular, allows * Allows control over an enabled {@linkplain FilterDef filter} at runtime.
* {@linkplain #setParameter(String, Object) arguments} to be assigned to * In particular, allows {@linkplain #setParameter(String, Object) arguments}
* parameters declared by the filter. * to be assigned to parameters declared by the filter.
* <p> * <p>
* A filter may be defined using {@link org.hibernate.annotations.FilterDef} * A filter may be defined using the annotations {@link FilterDef @FilterDef}
* and {@link org.hibernate.annotations.Filter}, and must be explicitly * and {@link org.hibernate.annotations.Filter @Filter}, but must be explicitly
* enabled at runtime by calling {@link Session#enableFilter(String)}. * enabled at runtime by calling {@link Session#enableFilter(String)}, unless
* the filter is declared as {@linkplain FilterDef#autoEnabled auto-enabled}.
* If, in a given session, a filter not declared {@code autoEnabled = true} is
* not explicitly enabled by calling {@code enableFilter()}, the filter will
* have no effect in that session.
* <p> * <p>
* Every parameter of the filter must be set immediately after * Every {@linkplain FilterDef#parameters parameter} of the filter must be
* supplied an argument by calling {@code setParameter()} immediately after
* {@code enableFilter()} is called, and before any other operation of the * {@code enableFilter()} is called, and before any other operation of the
* session is invoked. * session is invoked.
* *

View File

@ -17,7 +17,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* Specifies that an entity or collection is affected by a named * Specifies that an entity or collection is affected by a named
* filter declared using {@link FilterDef}, and allows the * filter declared using {@link FilterDef @FilterDef}, and allows the
* {@linkplain FilterDef#defaultCondition default filter condition} * {@linkplain FilterDef#defaultCondition default filter condition}
* to be overridden for the annotated entity or collection role. * to be overridden for the annotated entity or collection role.
* <p> * <p>

View File

@ -49,12 +49,17 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* <p> * <p>
* At runtime, a filter may be enabled in a particular session by * At runtime, a filter may be enabled in a particular session by
* calling {@link org.hibernate.Session#enableFilter(String)}, * calling {@link org.hibernate.Session#enableFilter(String)},
* passing the name of the filter, and then setting its parameters. * passing the name of the filter, and then supplying arguments to
* its parameters.
* <pre> * <pre>
* session.enableFilter("Current"); * session.enableFilter("Current");
* </pre> * </pre>
* <p> * <p>
* A filter has no effect unless it is explicitly enabled. * A filter has no effect unless:
* <ul>
* <li>it is explicitly enabled by calling {@code enableFilter}, or
* <li>it is declared {@link #autoEnabled autoEnabled = true}.
* </ul>
* *
* @author Matthew Inger * @author Matthew Inger
* @author Emmanuel Bernard * @author Emmanuel Bernard
@ -94,16 +99,31 @@ public @interface FilterDef {
ParamDef[] parameters() default {}; ParamDef[] parameters() default {};
/** /**
* The flag used to auto-enable the filter on the session. * Specifies that the filter auto-enabled, so that it is
* not necessary to call
* {@link org.hibernate.Session#enableFilter(String)}.
* <p>
* Arguments to {@linkplain #parameters} of auto-enabled
* filters are supplied via {@link ParamDef#resolver}.
*/ */
boolean autoEnabled() default false; boolean autoEnabled() default false;
/** /**
* The flag used to decide if the filter will * Specifies that the filter should be applied to operations
* be applied on direct fetches or not. * which fetch an entity by its identifier.
* <p> * <p>
* If the flag is true, the filter will be * By default, a filter does not apply to lookups by primary
* applied on direct fetches, such as {@link org.hibernate.Session#find(Class, Object)}. * key, for example, when:
* <ul>
* <li>{@linkplain org.hibernate.FetchMode fetching} a
* {@code @ManyToOne} association, or
* <li>{@link org.hibernate.Session#find(Class, Object) find()}
* is called.
* </ul>
* <p>
* If the effect of a filter with {@code applyToLoadByKey = true}
* would be to nullify a to-one association,
* {@link org.hibernate.EntityFilterException} is thrown.
*/ */
@Incubating @Incubating
boolean applyToLoadByKey() default false; boolean applyToLoadByKey() default false;

View File

@ -37,7 +37,7 @@ public @interface ParamDef {
* Generally deduced from the bind value. Allows to * Generally deduced from the bind value. Allows to
* specify a specific type to use. * specify a specific type to use.
* <p> * <p>
* The supplied Class can be one of the following:<ul> * The supplied {@link Class} may be one of the following:<ul>
* <li> * <li>
* a {@link org.hibernate.usertype.UserType} * a {@link org.hibernate.usertype.UserType}
* </li> * </li>
@ -48,19 +48,21 @@ public @interface ParamDef {
* a {@link org.hibernate.type.descriptor.java.JavaType} * a {@link org.hibernate.type.descriptor.java.JavaType}
* </li> * </li>
* <li> * <li>
* any Java type resolvable from {@link org.hibernate.type.descriptor.java.spi.JavaTypeRegistry} * any Java type resolvable from
* {@link org.hibernate.type.descriptor.java.spi.JavaTypeRegistry}
* </li> * </li>
* </ul> * </ul>
*/ */
Class<?> type(); Class<?> type();
/** /**
* The resolver to use when retrieving the parameter value. * A class implementing {@link Supplier} which provides arguments
* to this parameter. This is especially useful in the case of
* {@linkplain FilterDef#autoEnabled auto-enabled} filters.
* <p> * <p>
* The parameter value can either be defined using the {@link org.hibernate.Filter setParameter} * When a resolver is specified for a filter parameter, it's not
* method or by providing a resolver, that will be executed to retrieve the value. * necessary to provide an argument for the parameter by calling
* <p> * {@link org.hibernate.Filter#setParameter(String, Object)}.
* The supplied Class must implement {@link Supplier}
*/ */
Class<? extends Supplier> resolver() default Supplier.class; Class<? extends Supplier> resolver() default Supplier.class;
} }