improvements to typesafety of NaturalIdLoadAccess
and clean up its jdoc and the jdoc of its friends
This commit is contained in:
parent
5efa49f7d1
commit
76fa597d1b
|
@ -13,24 +13,36 @@ import org.hibernate.graph.RootGraph;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an entity by its primary identifier.
|
* Loads an entity by its primary identifier.
|
||||||
|
* <p>
|
||||||
|
* The interface is especially useful when customizing association
|
||||||
|
* fetching using an {@link jakarta.persistence.EntityGraph}.
|
||||||
|
* <pre>
|
||||||
|
* var graph = session.createEntityGraph(Book.class);
|
||||||
|
* graph.addSubgraph(Book_.publisher);
|
||||||
|
* graph.addPluralSubgraph(Book_.authors).addSubgraph(Author_.person);
|
||||||
|
* session.byId(Book.class).withFetchGraph(graph).load(bookId);
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author Eric Dalquist
|
* @author Eric Dalquist
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
*
|
||||||
|
* @see Session#byId(Class)
|
||||||
*/
|
*/
|
||||||
public interface IdentifierLoadAccess<T> {
|
public interface IdentifierLoadAccess<T> {
|
||||||
/**
|
/**
|
||||||
* Specify the {@link LockOptions} to use when retrieving the entity.
|
* Specify the {@linkplain LockOptions lock options} to use when
|
||||||
|
* querying the database.
|
||||||
*
|
*
|
||||||
* @param lockOptions The lock options to use.
|
* @param lockOptions The lock options to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
IdentifierLoadAccess<T> with(LockOptions lockOptions);
|
IdentifierLoadAccess<T> with(LockOptions lockOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the {@link CacheMode} to use when retrieving the entity.
|
* Specify the {@link CacheMode} to use when obtaining an entity.
|
||||||
*
|
*
|
||||||
* @param cacheMode The CacheMode to use.
|
* @param cacheMode The {@code CacheMode} to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
|
@ -43,10 +55,20 @@ public interface IdentifierLoadAccess<T> {
|
||||||
*/
|
*/
|
||||||
IdentifierLoadAccess<T> withReadOnly(boolean readOnly);
|
IdentifierLoadAccess<T> withReadOnly(boolean readOnly);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the associations fetched by default by specifying
|
||||||
|
* the complete list of associations to be fetched as an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph}.
|
||||||
|
*/
|
||||||
default IdentifierLoadAccess<T> withFetchGraph(RootGraph<T> graph) {
|
default IdentifierLoadAccess<T> withFetchGraph(RootGraph<T> graph) {
|
||||||
return with( graph, GraphSemantic.FETCH );
|
return with( graph, GraphSemantic.FETCH );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment the associations fetched by default by specifying a
|
||||||
|
* list of additional associations to be fetched as an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph}.
|
||||||
|
*/
|
||||||
default IdentifierLoadAccess<T> withLoadGraph(RootGraph<T> graph) {
|
default IdentifierLoadAccess<T> withLoadGraph(RootGraph<T> graph) {
|
||||||
return with( graph, GraphSemantic.LOAD );
|
return with( graph, GraphSemantic.LOAD );
|
||||||
}
|
}
|
||||||
|
@ -59,15 +81,22 @@ public interface IdentifierLoadAccess<T> {
|
||||||
return withLoadGraph( graph );
|
return withLoadGraph( graph );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize the associations fetched by specifying an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph},
|
||||||
|
* and how it should be {@linkplain GraphSemantic interpreted}.
|
||||||
|
*/
|
||||||
IdentifierLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
IdentifierLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance with the given identifier, assuming that the instance exists. This method
|
* Return the persistent instance with the given identifier, assuming
|
||||||
* might return a proxied instance that is initialized on-demand, when a non-identifier method is accessed.
|
* that the instance exists. This method might return a proxied instance
|
||||||
|
* that is initialized on-demand, when a non-identifier method is accessed.
|
||||||
* <p>
|
* <p>
|
||||||
* You should not use this method to determine if an instance exists; to check for existence, use {@link #load}
|
* You should not use this method to determine if an instance exists;
|
||||||
* instead. Use this only to retrieve an instance that you assume exists, where non-existence would be an
|
* to check for existence, use {@link #load} instead. Use this only to
|
||||||
* actual error.
|
* retrieve an instance that you assume exists, where non-existence would
|
||||||
|
* be an actual error.
|
||||||
*
|
*
|
||||||
* @param id The identifier for which to obtain a reference
|
* @param id The identifier for which to obtain a reference
|
||||||
*
|
*
|
||||||
|
@ -76,9 +105,10 @@ public interface IdentifierLoadAccess<T> {
|
||||||
T getReference(Object id);
|
T getReference(Object id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance with the given identifier, or null if there is no such persistent instance.
|
* Return the persistent instance with the given identifier, or null
|
||||||
* If the instance is already associated with the session, return that instance, initializing it if needed. This
|
* if there is no such persistent instance. If the instance is already
|
||||||
* method never returns an uninitialized instance.
|
* associated with the session, return that instance, initializing it
|
||||||
|
* if needed. This method never returns an uninitialized instance.
|
||||||
*
|
*
|
||||||
* @param id The identifier
|
* @param id The identifier
|
||||||
*
|
*
|
||||||
|
@ -87,12 +117,12 @@ public interface IdentifierLoadAccess<T> {
|
||||||
T load(Object id);
|
T load(Object id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same semantic as {@link #load} except that here {@link Optional} is returned to
|
* Just like {@link #load}, except that here an {@link Optional} is
|
||||||
* handle nullability.
|
* returned.
|
||||||
*
|
*
|
||||||
* @param id The identifier
|
* @param id The identifier
|
||||||
*
|
*
|
||||||
* @return The persistent instance, if one, wrapped in Optional
|
* @return The persistent instance, if any, as an {@link Optional}
|
||||||
*/
|
*/
|
||||||
Optional<T> loadOptional(Object id);
|
Optional<T> loadOptional(Object id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,34 +12,53 @@ import org.hibernate.graph.GraphSemantic;
|
||||||
import org.hibernate.graph.RootGraph;
|
import org.hibernate.graph.RootGraph;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads multiple entities at once by identifiers, ultimately via one of the
|
* Loads multiple instances of a given entity type at once, by
|
||||||
* {@link #multiLoad} methods, using the various options specified (if any)
|
* specifying a list of identifier values. This allows the entities
|
||||||
|
* to be fetched from the database in batches.
|
||||||
|
* <pre>
|
||||||
|
* var graph = session.createEntityGraph(Book.class);
|
||||||
|
* graph.addSubgraph(Book_.publisher);
|
||||||
|
* session.byId(Book.class).withFetchGraph(graph).multiLoad(bookIds);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see Session#byMultipleIds(Class)
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface MultiIdentifierLoadAccess<T> {
|
public interface MultiIdentifierLoadAccess<T> {
|
||||||
/**
|
/**
|
||||||
* Specify the {@link LockOptions} to use when retrieving the entity.
|
* Specify the {@linkplain LockOptions lock options} to use when
|
||||||
|
* querying the database.
|
||||||
*
|
*
|
||||||
* @param lockOptions The lock options to use.
|
* @param lockOptions The lock options to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
MultiIdentifierLoadAccess<T> with(LockOptions lockOptions);
|
MultiIdentifierLoadAccess<T> with(LockOptions lockOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the {@link CacheMode} to use when retrieving the entity.
|
* Specify the {@link CacheMode} to use when obtaining an entity.
|
||||||
*
|
*
|
||||||
* @param cacheMode The CacheMode to use.
|
* @param cacheMode The {@code CacheMode} to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
MultiIdentifierLoadAccess<T> with(CacheMode cacheMode);
|
MultiIdentifierLoadAccess<T> with(CacheMode cacheMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the associations fetched by default by specifying
|
||||||
|
* the complete list of associations to be fetched as an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph}.
|
||||||
|
*/
|
||||||
default MultiIdentifierLoadAccess<T> withFetchGraph(RootGraph<T> graph) {
|
default MultiIdentifierLoadAccess<T> withFetchGraph(RootGraph<T> graph) {
|
||||||
return with( graph, GraphSemantic.FETCH );
|
return with( graph, GraphSemantic.FETCH );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment the associations fetched by default by specifying a
|
||||||
|
* list of additional associations to be fetched as an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph}.
|
||||||
|
*/
|
||||||
default MultiIdentifierLoadAccess<T> withLoadGraph(RootGraph<T> graph) {
|
default MultiIdentifierLoadAccess<T> withLoadGraph(RootGraph<T> graph) {
|
||||||
return with( graph, GraphSemantic.LOAD );
|
return with( graph, GraphSemantic.LOAD );
|
||||||
}
|
}
|
||||||
|
@ -52,16 +71,28 @@ public interface MultiIdentifierLoadAccess<T> {
|
||||||
return with( graph, GraphSemantic.LOAD );
|
return with( graph, GraphSemantic.LOAD );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize the associations fetched by specifying an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph},
|
||||||
|
* and how it should be {@linkplain GraphSemantic interpreted}.
|
||||||
|
*/
|
||||||
MultiIdentifierLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
MultiIdentifierLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a batch size for loading the entities (how many at a time). The default is
|
* Specify a batch size, that is, how many entities should be
|
||||||
* to use a batch sizing strategy defined by the Dialect in use. Any greater-than-one
|
* fetched in each request to the database.
|
||||||
* value here will override that default behavior. If giving an explicit value here,
|
* <ul>
|
||||||
* care should be taken to not exceed the capabilities of the underlying database.
|
* <li>By default, the batch sizing strategy is determined by the
|
||||||
|
* {@linkplain org.hibernate.dialect.Dialect#getBatchLoadSizingStrategy
|
||||||
|
* SQL dialect}, but
|
||||||
|
* <li>if some {@code batchSize>1} is specified as an
|
||||||
|
* argument to this method, then that batch size will be used.
|
||||||
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Note that overall a batch-size is considered a hint. How the underlying loading
|
* If an explicit batch size is set manually, care should be taken
|
||||||
* mechanism interprets that is completely up to that underlying loading mechanism.
|
* to not exceed the capabilities of the underlying database.
|
||||||
|
* <p>
|
||||||
|
* A batch size is considered a hint.
|
||||||
*
|
*
|
||||||
* @param batchSize The batch size
|
* @param batchSize The batch size
|
||||||
*
|
*
|
||||||
|
@ -70,53 +101,58 @@ public interface MultiIdentifierLoadAccess<T> {
|
||||||
MultiIdentifierLoadAccess<T> withBatchSize(int batchSize);
|
MultiIdentifierLoadAccess<T> withBatchSize(int batchSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify whether we should check the {@link Session} to see whether the first-level cache already contains any of the
|
* Specifies whether the ids of managed entity instances already
|
||||||
* entities to be loaded in a managed state <b>for the purpose of not including those
|
* cached in the current persistence context should be excluded
|
||||||
* ids to the batch-load SQL</b>.
|
* from the list of ids sent to the database.
|
||||||
|
* <p>
|
||||||
|
* By default, all ids are included and sent to the database.
|
||||||
*
|
*
|
||||||
* @param enabled {@code true} enables this checking; {@code false} (the default) disables it.
|
* @param enabled {@code true} if they should be excluded;
|
||||||
|
* {@code false} if they should be included.
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
MultiIdentifierLoadAccess<T> enableSessionCheck(boolean enabled);
|
MultiIdentifierLoadAccess<T> enableSessionCheck(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the multi-load operation be allowed to return entities that are locally
|
* Should {@link #multiLoad} return entity instances that have been
|
||||||
* deleted? A locally deleted entity is one which has been passed to this
|
* {@link Session#remove(Object) marked for removal} in the current
|
||||||
* Session's {@link Session#delete} / {@link Session#remove} method, but not
|
* session, but not yet {@code delete}d in the database?
|
||||||
* yet flushed. The default behavior is to handle them as null in the return
|
* <p>
|
||||||
* (see {@link #enableOrderedReturn}).
|
* By default, instances marked for removal are replaced by null in
|
||||||
|
* the returned list of entities when {@link #enableOrderedReturn}
|
||||||
|
* is used.
|
||||||
*
|
*
|
||||||
* @param enabled {@code true} enables returning the deleted entities;
|
* @param enabled {@code true} if removed entities should be returned;
|
||||||
* {@code false} (the default) disables it.
|
* {@code false} if they should be replaced by null values.
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
MultiIdentifierLoadAccess<T> enableReturnOfDeletedEntities(boolean enabled);
|
MultiIdentifierLoadAccess<T> enableReturnOfDeletedEntities(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the return List be ordered and positional in relation to the
|
* Should the returned list of entity instances be ordered, with the
|
||||||
* incoming ids? If enabled (the default), the return List is ordered and
|
* position of an entity instance determined by the position of its
|
||||||
* positional relative to the incoming ids. In other words, a request to
|
* identifier in the list if ids passed to {@link #multiLoad}?
|
||||||
* {@code multiLoad([2,1,3])} will return {@code [Entity#2, Entity#1, Entity#3]}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* An important distinction is made here in regards to the handling of
|
* By default, the returned list is ordered and the positions of the
|
||||||
* unknown entities depending on this "ordered return" setting. If enabled
|
* entities correspond to the positions of their ids. In this case,
|
||||||
* a null is inserted into the List at the proper position(s). If disabled,
|
* the {@linkplain #enableReturnOfDeletedEntities handling of entities
|
||||||
* the nulls are not put into the return List. In other words, consumers of
|
* marked for removal} becomes important.
|
||||||
* the returned ordered List would need to be able to handle null elements.
|
|
||||||
*
|
*
|
||||||
* @param enabled {@code true} (the default) enables ordering;
|
* @param enabled {@code true} if entity instances should be ordered;
|
||||||
* {@code false} disables it.
|
* {@code false} if they may be returned in any order.
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
MultiIdentifierLoadAccess<T> enableOrderedReturn(boolean enabled);
|
MultiIdentifierLoadAccess<T> enableOrderedReturn(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a load of multiple entities by identifiers. See {@link #enableOrderedReturn}
|
* Retrieve the entities with the given identifiers.
|
||||||
* and {@link #enableReturnOfDeletedEntities} for options which effect
|
* <p>
|
||||||
* the size and "shape" of the return list.
|
* Note that the options {@link #enableReturnOfDeletedEntities} and
|
||||||
|
* {@link #enableOrderedReturn} affect the size and shape of the
|
||||||
|
* returned list of entity instances.
|
||||||
*
|
*
|
||||||
* @param <K> The identifier type
|
* @param <K> The identifier type
|
||||||
*
|
*
|
||||||
|
@ -126,9 +162,11 @@ public interface MultiIdentifierLoadAccess<T> {
|
||||||
<K> List<T> multiLoad(K... ids);
|
<K> List<T> multiLoad(K... ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a load of multiple entities by identifiers. See {@link #enableOrderedReturn}
|
* Retrieve the entities with the given identifiers.
|
||||||
* and {@link #enableReturnOfDeletedEntities} for options which effect
|
* <p>
|
||||||
* the size and "shape" of the return list.
|
* Note that the options {@link #enableReturnOfDeletedEntities} and
|
||||||
|
* {@link #enableOrderedReturn} affect the size and shape of the
|
||||||
|
* returned list of entity instances.
|
||||||
*
|
*
|
||||||
* @param ids The ids to load
|
* @param ids The ids to load
|
||||||
* @param <K> The identifier type
|
* @param <K> The identifier type
|
||||||
|
|
|
@ -6,24 +6,37 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate;
|
package org.hibernate;
|
||||||
|
|
||||||
|
import jakarta.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an entity by its natural identifier.
|
* Loads an entity by its natural identifier, which may be a
|
||||||
|
* composite value comprising more than one attribute of the
|
||||||
|
* entity. If the entity has exactly one attribute annotated
|
||||||
|
* {@link org.hibernate.annotations.NaturalId @NaturalId},
|
||||||
|
* then {@link SimpleNaturalIdLoadAccess} may be used instead.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a generic form of load-by-natural-id covering both a single attribute
|
* <pre>
|
||||||
* and multiple attributes as the natural-id. For natural-ids defined by a single
|
* Book book =
|
||||||
* attribute, {@link SimpleNaturalIdLoadAccess} offers simplified access.
|
* session.byNaturalId(Book.class)
|
||||||
|
* .using(Book_.isbn, isbn)
|
||||||
|
* .using(Book_.printing, printing)
|
||||||
|
* .load();
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author Eric Dalquist
|
* @author Eric Dalquist
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*
|
*
|
||||||
|
* @see Session#byNaturalId(Class)
|
||||||
* @see org.hibernate.annotations.NaturalId
|
* @see org.hibernate.annotations.NaturalId
|
||||||
* @see Session#byNaturalId
|
* @see SimpleNaturalIdLoadAccess
|
||||||
*/
|
*/
|
||||||
public interface NaturalIdLoadAccess<T> {
|
public interface NaturalIdLoadAccess<T> {
|
||||||
/**
|
/**
|
||||||
* Specify the {@link LockOptions} to use when retrieving the entity.
|
* Specify the {@linkplain LockOptions lock options} to use when
|
||||||
|
* querying the database.
|
||||||
*
|
*
|
||||||
* @param lockOptions The lock options to use.
|
* @param lockOptions The lock options to use.
|
||||||
*
|
*
|
||||||
|
@ -32,9 +45,23 @@ public interface NaturalIdLoadAccess<T> {
|
||||||
NaturalIdLoadAccess<T> with(LockOptions lockOptions);
|
NaturalIdLoadAccess<T> with(LockOptions lockOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a NaturalId attribute value.
|
* Add a {@link org.hibernate.annotations.NaturalId @NaturalId}
|
||||||
|
* attribute value in a typesafe way.
|
||||||
*
|
*
|
||||||
* @param attributeName The entity attribute name that is marked as a NaturalId
|
* @param attribute A typesafe reference to an attribute of the
|
||||||
|
* entity that is annotated {@code @NaturalId}
|
||||||
|
* @param value The value of the attribute
|
||||||
|
*
|
||||||
|
* @return {@code this}, for method chaining
|
||||||
|
*/
|
||||||
|
<X> NaturalIdLoadAccess<T> using(SingularAttribute<? super T, X> attribute, X value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a {@link org.hibernate.annotations.NaturalId @NaturalId}
|
||||||
|
* attribute value.
|
||||||
|
*
|
||||||
|
* @param attributeName The name of an attribute of the entity
|
||||||
|
* that is annotated {@code @NaturalId}
|
||||||
* @param value The value of the attribute
|
* @param value The value of the attribute
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
|
@ -42,24 +69,54 @@ public interface NaturalIdLoadAccess<T> {
|
||||||
NaturalIdLoadAccess<T> using(String attributeName, Object value);
|
NaturalIdLoadAccess<T> using(String attributeName, Object value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set multiple natural-id attribute values at once. The passed array is
|
* Set multiple {@link org.hibernate.annotations.NaturalId @NaturalId}
|
||||||
* expected to have an even number of elements, with the attribute name followed
|
* attribute values at once. An even number of arguments is expected,
|
||||||
* by its value, for example, {@code using( "system", "matrix", "username", "neo" )}.
|
* with each attribute name followed by its value, for example:
|
||||||
|
* <pre>
|
||||||
|
* Book book =
|
||||||
|
* session.byNaturalId(Book.class)
|
||||||
|
* .using(Map.of(Book_.ISBN, isbn, Book_.PRINTING, printing))
|
||||||
|
* .load();
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
|
NaturalIdLoadAccess<T> using(Map<String,?> mappings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set multiple {@link org.hibernate.annotations.NaturalId @NaturalId}
|
||||||
|
* attribute values at once. An even number of arguments is expected,
|
||||||
|
* with each attribute name followed by its value, for example:
|
||||||
|
* <pre>
|
||||||
|
* Book book =
|
||||||
|
* session.byNaturalId(Book.class)
|
||||||
|
* .using(Book_.ISBN, isbn, Book_.PRINTING, printing)
|
||||||
|
* .load();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return {@code this}, for method chaining
|
||||||
|
*
|
||||||
|
* @deprecated use {@link #using(Map)} with {@link Map#of}, which is
|
||||||
|
* slightly more typesafe
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6.3")
|
||||||
NaturalIdLoadAccess<T> using(Object... mappings);
|
NaturalIdLoadAccess<T> using(Object... mappings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For entities with mutable natural ids, should natural ids be synchronized prior to performing a lookup?
|
* For entities with mutable natural ids, should natural ids be
|
||||||
* The default, for correctness, is to synchronize.
|
* synchronized prior to executing a query? The default, for
|
||||||
|
* correctness, is to synchronize.
|
||||||
* <p>
|
* <p>
|
||||||
* Here "synchronization" means updating the natural id to primary key cross-reference maintained by the
|
* Here "synchronization" means updating the natural id to
|
||||||
* session. When enabled, prior to performing the lookup, Hibernate will check all entities of the given
|
* primary key cross-reference maintained by the session. When
|
||||||
* type associated with the session to see if any natural id values have changed and, if so, update the
|
* enabled, prior to performing the lookup, Hibernate will check
|
||||||
* cross-reference. There is a performance penalty associated with this, so if it is completely certain
|
* all entities of the given type associated with the session to
|
||||||
* the no natural id in play has changed, this setting can be disabled to circumvent that impact.
|
* see if any natural id values have changed and, if so, update
|
||||||
* Disabling this setting when natural id values <em>have</em> changed can result in incorrect results!
|
* the cross-reference. There is a performance penalty associated
|
||||||
|
* with this, so if it is completely certain the no natural id in
|
||||||
|
* play has changed, this setting can be disabled to circumvent
|
||||||
|
* that impact. Disabling this setting when natural id values
|
||||||
|
* <em>have</em> changed can lead to incorrect results!
|
||||||
*
|
*
|
||||||
* @param enabled Should synchronization be performed?
|
* @param enabled Should synchronization be performed?
|
||||||
* {@code true} indicates synchronization will be performed;
|
* {@code true} indicates synchronization will be performed;
|
||||||
|
@ -70,31 +127,36 @@ public interface NaturalIdLoadAccess<T> {
|
||||||
NaturalIdLoadAccess<T> setSynchronizationEnabled(boolean enabled);
|
NaturalIdLoadAccess<T> setSynchronizationEnabled(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance with the natural id value(s) defined by the call(s) to {@link #using}. This
|
* Return the persistent instance with the full natural id specified
|
||||||
* method might return a proxied instance that is initialized on-demand, when a non-identifier method is accessed.
|
* by previous calls to {@link #using}. This method might return a
|
||||||
|
* proxied instance that is initialized on-demand, when a non-identifier
|
||||||
|
* method is accessed.
|
||||||
* <p>
|
* <p>
|
||||||
* You should not use this method to determine if an instance exists; to check for existence, use {@link #load}
|
* You should not use this method to determine if an instance exists;
|
||||||
* instead. Use this only to retrieve an instance that you assume exists, where non-existence would be an
|
* to check for existence, use {@link #load} instead. Use this method
|
||||||
* actual error.
|
* only to retrieve an instance that you assume exists, where
|
||||||
|
* non-existence would be an actual error.
|
||||||
*
|
*
|
||||||
* @return the persistent instance or proxy
|
* @return the persistent instance or proxy
|
||||||
*/
|
*/
|
||||||
T getReference();
|
T getReference();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance with the natural id value(s) defined by the call(s) to {@link #using}, or
|
* Return the persistent instance with the full natural id specified
|
||||||
* {@code null} if there is no such persistent instance. If the instance is already associated with the session,
|
* by previous calls to {@link #using}, or {@code null} if there is no
|
||||||
* return that instance, initializing it if needed. This method never returns an uninitialized instance.
|
* such persistent instance. If the instance is already associated with
|
||||||
|
* the session, return that instance, initializing it if needed. This
|
||||||
|
* method never returns an uninitialized instance.
|
||||||
*
|
*
|
||||||
* @return The persistent instance or {@code null}
|
* @return The persistent instance or {@code null}
|
||||||
*/
|
*/
|
||||||
T load();
|
T load();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same semantic as {@link #load} except that here {@link Optional} is returned to
|
* Just like {@link #load}, except that here an {@link Optional} is
|
||||||
* handle nullability.
|
* returned.
|
||||||
*
|
*
|
||||||
* @return The persistent instance, if one, wrapped in Optional
|
* @return The persistent instance, if one, as an {@link Optional}
|
||||||
*/
|
*/
|
||||||
Optional<T> loadOptional();
|
Optional<T> loadOptional();
|
||||||
|
|
||||||
|
|
|
@ -11,34 +11,60 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.graph.GraphSemantic;
|
import org.hibernate.graph.GraphSemantic;
|
||||||
import org.hibernate.graph.RootGraph;
|
import org.hibernate.graph.RootGraph;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
|
||||||
|
import static org.hibernate.internal.util.collections.CollectionHelper.asMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the ability to load multiple entities by simple natural-id simultaneously.
|
* Loads multiple instances of a given entity type at once, by
|
||||||
|
* specifying a list of natural id values. This allows the entities
|
||||||
|
* to be fetched from the database in batches.
|
||||||
|
* <p>
|
||||||
|
* Composite natural ids may be accommodated by passing a list of
|
||||||
|
* maps of type {@code Map<String,Object>} to {@link #multiLoad}.
|
||||||
|
* Each map must contain the natural id attribute values keyed by
|
||||||
|
* {@link org.hibernate.annotations.NaturalId @NaturalId} attribute
|
||||||
|
* name.
|
||||||
|
* <pre>
|
||||||
|
* var compositeNaturalId =
|
||||||
|
* Map.of(Book_.ISBN, isbn, Book_.PRINTING, printing);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see Session#byMultipleNaturalId(Class)
|
||||||
*/
|
*/
|
||||||
public interface NaturalIdMultiLoadAccess<T> {
|
public interface NaturalIdMultiLoadAccess<T> {
|
||||||
/**
|
/**
|
||||||
* Specify the {@link LockOptions} to use when retrieving the entity.
|
* Specify the {@linkplain LockOptions lock options} to use when
|
||||||
|
* querying the database.
|
||||||
*
|
*
|
||||||
* @param lockOptions The lock options to use.
|
* @param lockOptions The lock options to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
NaturalIdMultiLoadAccess<T> with(LockOptions lockOptions);
|
NaturalIdMultiLoadAccess<T> with(LockOptions lockOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the {@link CacheMode} to use when retrieving the entity.
|
* Specify the {@link CacheMode} to use when obtaining an entity.
|
||||||
*
|
*
|
||||||
* @param cacheMode The CacheMode to use.
|
* @param cacheMode The {@code CacheMode} to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
NaturalIdMultiLoadAccess<T> with(CacheMode cacheMode);
|
NaturalIdMultiLoadAccess<T> with(CacheMode cacheMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the associations fetched by default by specifying
|
||||||
|
* the complete list of associations to be fetched as an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph}.
|
||||||
|
*/
|
||||||
default NaturalIdMultiLoadAccess<T> withFetchGraph(RootGraph<T> graph) {
|
default NaturalIdMultiLoadAccess<T> withFetchGraph(RootGraph<T> graph) {
|
||||||
return with( graph, GraphSemantic.FETCH );
|
return with( graph, GraphSemantic.FETCH );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment the associations fetched by default by specifying a
|
||||||
|
* list of additional associations to be fetched as an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph}.
|
||||||
|
*/
|
||||||
default NaturalIdMultiLoadAccess<T> withLoadGraph(RootGraph<T> graph) {
|
default NaturalIdMultiLoadAccess<T> withLoadGraph(RootGraph<T> graph) {
|
||||||
return with( graph, GraphSemantic.LOAD );
|
return with( graph, GraphSemantic.LOAD );
|
||||||
}
|
}
|
||||||
|
@ -52,17 +78,27 @@ public interface NaturalIdMultiLoadAccess<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a load or fetch graph to be used when retrieving the entity
|
* Customize the associations fetched by specifying an
|
||||||
|
* {@linkplain jakarta.persistence.EntityGraph entity graph},
|
||||||
|
* and how it should be {@linkplain GraphSemantic interpreted}.
|
||||||
*/
|
*/
|
||||||
NaturalIdMultiLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
NaturalIdMultiLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a batch size for loading the entities (how many at a time). The default is
|
* Specify a batch size, that is, how many entities should be
|
||||||
* to use a batch sizing strategy defined by the Dialect in use. Any greater-than-one
|
* fetched in each request to the database.
|
||||||
* value here will override that default behavior. If giving an explicit value here,
|
* <ul>
|
||||||
* care should be taken to not exceed the capabilities of the underlying database.
|
* <li>By default, the batch sizing strategy is determined by the
|
||||||
|
* {@linkplain org.hibernate.dialect.Dialect#getBatchLoadSizingStrategy
|
||||||
|
* SQL dialect}, but
|
||||||
|
* <li>if some {@code batchSize>1} is specified as an
|
||||||
|
* argument to this method, then that batch size will be used.
|
||||||
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Note that overall a batch-size is considered a hint.
|
* If an explicit batch size is set manually, care should be taken
|
||||||
|
* to not exceed the capabilities of the underlying database.
|
||||||
|
* <p>
|
||||||
|
* A batch size is considered a hint.
|
||||||
*
|
*
|
||||||
* @param batchSize The batch size
|
* @param batchSize The batch size
|
||||||
*
|
*
|
||||||
|
@ -71,68 +107,75 @@ public interface NaturalIdMultiLoadAccess<T> {
|
||||||
NaturalIdMultiLoadAccess<T> withBatchSize(int batchSize);
|
NaturalIdMultiLoadAccess<T> withBatchSize(int batchSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the multi-load operation be allowed to return entities that are locally
|
* Should {@link #multiLoad} return entity instances that have been
|
||||||
* deleted? A locally deleted entity is one which has been passed to this
|
* {@link Session#remove(Object) marked for removal} in the current
|
||||||
* Session's {@link Session#delete} / {@link Session#remove} method, but not
|
* session, but not yet {@code delete}d in the database?
|
||||||
* yet flushed. The default behavior is to handle them as null in the return
|
* <p>
|
||||||
* (see {@link #enableOrderedReturn}).
|
* By default, instances marked for removal are replaced by null in
|
||||||
|
* the returned list of entities when {@link #enableOrderedReturn}
|
||||||
|
* is used.
|
||||||
*
|
*
|
||||||
* @param enabled {@code true} enables returning the deleted entities;
|
* @param enabled {@code true} if removed entities should be returned;
|
||||||
* {@code false} (the default) disables it.
|
* {@code false} if they should be replaced by null values.
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
NaturalIdMultiLoadAccess<T> enableReturnOfDeletedEntities(boolean enabled);
|
NaturalIdMultiLoadAccess<T> enableReturnOfDeletedEntities(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the return List be ordered and positional in relation to the
|
* Should the returned list of entity instances be ordered, with the
|
||||||
* incoming ids? If enabled (the default), the return List is ordered and
|
* position of an entity instance determined by the position of its
|
||||||
* positional relative to the incoming ids. In other words, a request to
|
* identifier in the list if ids passed to {@link #multiLoad}?
|
||||||
* {@code multiLoad([2,1,3])} will return {@code [Entity#2, Entity#1, Entity#3]}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* An important distinction is made here in regards to the handling of
|
* By default, the returned list is ordered and the positions of the
|
||||||
* unknown entities depending on this "ordered return" setting. If enabled
|
* entities correspond to the positions of their ids. In this case,
|
||||||
* a null is inserted into the List at the proper position(s). If disabled,
|
* the {@linkplain #enableReturnOfDeletedEntities handling of entities
|
||||||
* the nulls are not put into the return List. In other words, consumers of
|
* marked for removal} becomes important.
|
||||||
* the returned ordered List would need to be able to handle null elements.
|
|
||||||
*
|
*
|
||||||
* @param enabled {@code true} (the default) enables ordering;
|
* @param enabled {@code true} if entity instances should be ordered;
|
||||||
* {@code false} disables it.
|
* {@code false} if they may be returned in any order.
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
NaturalIdMultiLoadAccess<T> enableOrderedReturn(boolean enabled);
|
NaturalIdMultiLoadAccess<T> enableOrderedReturn(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a load of multiple entities by natural-id.
|
* Retrieve the entities with the given natural id values.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link #enableOrderedReturn} and {@link #enableReturnOfDeletedEntities}
|
* Note that the options {@link #enableReturnOfDeletedEntities} and
|
||||||
* for options which effect the size and "shape" of the return list.
|
* {@link #enableOrderedReturn} affect the size and shape of the
|
||||||
|
* returned list of entity instances.
|
||||||
*
|
*
|
||||||
* @param ids The natural-id values to load
|
* @param ids The natural id values to load
|
||||||
*
|
*
|
||||||
* @return The managed entities.
|
* @return The managed entities.
|
||||||
*/
|
*/
|
||||||
List<T> multiLoad(Object... ids);
|
List<T> multiLoad(Object... ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a load of multiple entities by natural-id.
|
* Retrieve the entities with the given natural id values.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link #enableOrderedReturn} and {@link #enableReturnOfDeletedEntities}
|
* Note that the options {@link #enableReturnOfDeletedEntities} and
|
||||||
* for options which effect the size and "shape" of the return list.
|
* {@link #enableOrderedReturn} affect the size and shape of the
|
||||||
|
* returned list of entity instances.
|
||||||
*
|
*
|
||||||
* @param ids The natural-id values to load
|
* @param ids The natural id values to load
|
||||||
*
|
*
|
||||||
* @return The managed entities.
|
* @return The managed entities.
|
||||||
*/
|
*/
|
||||||
List<T> multiLoad(List<?> ids);
|
List<T> multiLoad(List<?> ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for creating a Map that represents the value of a compound natural-id
|
* Helper for creating a {@link Map} that represents the value of a
|
||||||
* for use in loading. The passed array is expected to have an even number of elements
|
* composite natural id. An even number of arguments is expected,
|
||||||
* representing key, value pairs. E.g. `using( "system", "matrix", "username", "neo" )`
|
* with each attribute name followed by its value.
|
||||||
|
*
|
||||||
|
* @see NaturalIdLoadAccess#using(Object...)
|
||||||
|
*
|
||||||
|
* @deprecated use {@link Map#of} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.3")
|
||||||
static Map<String,?> compoundValue(Object... elements) {
|
static Map<String,?> compoundValue(Object... elements) {
|
||||||
return CollectionHelper.asMap( elements );
|
return asMap( elements );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,69 +9,88 @@ package org.hibernate;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an entity by its natural identifier.
|
* Loads an entity by its natural identifier. This simplified API is
|
||||||
|
* used when the entity has exactly one field or property annotated
|
||||||
|
* {@link org.hibernate.annotations.NaturalId @NaturalId}. If an
|
||||||
|
* entity has multiple attributes annotated {@code @NaturalId}, then
|
||||||
|
* {@link NaturalIdLoadAccess} should be used instead.
|
||||||
|
* <p>
|
||||||
|
* <pre>
|
||||||
|
* Book book = session.bySimpleNaturalId(Book.class).load(isbn);
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author Eric Dalquist
|
* @author Eric Dalquist
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*
|
*
|
||||||
|
* @see Session#bySimpleNaturalId(Class)
|
||||||
* @see org.hibernate.annotations.NaturalId
|
* @see org.hibernate.annotations.NaturalId
|
||||||
* @see NaturalIdLoadAccess
|
* @see NaturalIdLoadAccess
|
||||||
*/
|
*/
|
||||||
public interface SimpleNaturalIdLoadAccess<T> {
|
public interface SimpleNaturalIdLoadAccess<T> {
|
||||||
/**
|
/**
|
||||||
* Specify the {@link LockOptions} to use when retrieving the entity.
|
* Specify the {@linkplain LockOptions lock options} to use when
|
||||||
|
* querying the database.
|
||||||
*
|
*
|
||||||
* @param lockOptions The lock options to use.
|
* @param lockOptions The lock options to use
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
SimpleNaturalIdLoadAccess<T> with(LockOptions lockOptions);
|
SimpleNaturalIdLoadAccess<T> with(LockOptions lockOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For entities with mutable natural ids, should Hibernate perform "synchronization" prior to performing
|
* For entities with mutable natural ids, should Hibernate perform
|
||||||
* lookups? The default is to perform "synchronization" (for correctness).
|
* "synchronization" prior to performing lookups? The default is
|
||||||
|
* to perform "synchronization" (for correctness).
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link NaturalIdLoadAccess#setSynchronizationEnabled} for detailed discussion.
|
* See {@link NaturalIdLoadAccess#setSynchronizationEnabled} for
|
||||||
|
* detailed discussion.
|
||||||
*
|
*
|
||||||
* @param enabled Should synchronization be performed? {@code true} indicates synchronization will be performed;
|
* @param enabled Should synchronization be performed?
|
||||||
* {@code false} indicates it will be circumvented.
|
* {@code true} indicates synchronization will be performed;
|
||||||
|
* {@code false} indicates it will be circumvented.
|
||||||
*
|
*
|
||||||
* @return {@code this}, for method chaining
|
* @return {@code this}, for method chaining
|
||||||
*/
|
*/
|
||||||
SimpleNaturalIdLoadAccess<T> setSynchronizationEnabled(boolean enabled);
|
SimpleNaturalIdLoadAccess<T> setSynchronizationEnabled(boolean enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance with the given natural id value, assuming that the instance exists. This method
|
* Return the persistent instance with the given natural id value,
|
||||||
* might return a proxied instance that is initialized on-demand, when a non-identifier method is accessed.
|
* assuming that the instance exists. This method might return a
|
||||||
|
* proxied instance that is initialized on-demand, when a
|
||||||
|
* non-identifier method is accessed.
|
||||||
|
* <p>
|
||||||
|
* You should not use this method to determine if an instance exists;
|
||||||
|
* to check for existence, use {@link #load} instead. Use this only to
|
||||||
|
* retrieve an instance that you assume exists, where non-existence
|
||||||
|
* would be an actual error.
|
||||||
*
|
*
|
||||||
* You should not use this method to determine if an instance exists; to check for existence, use {@link #load}
|
* @param naturalIdValue The value of the natural id
|
||||||
* instead. Use this only to retrieve an instance that you assume exists, where non-existence would be an
|
|
||||||
* actual error.
|
|
||||||
*
|
*
|
||||||
* @param naturalIdValue The value of the natural-id for the entity to retrieve
|
* @return The persistent instance or proxy, if an instance exists.
|
||||||
*
|
* Otherwise, {@code null}.
|
||||||
* @return The persistent instance or proxy, if an instance exists. Otherwise, {@code null}.
|
|
||||||
*/
|
*/
|
||||||
T getReference(Object naturalIdValue);
|
T getReference(Object naturalIdValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance with the given natural id value, or {@code null} if there is no such persistent
|
* Return the persistent instance with the given natural id value,
|
||||||
* instance. If the instance is already associated with the session, return that instance, initializing it if
|
* or {@code null} if there is no such persistent instance. If the
|
||||||
* needed. This method never returns an uninitialized instance.
|
* instance is already associated with the session, return that
|
||||||
|
* instance, initializing it if needed. This method never returns
|
||||||
|
* an uninitialized instance.
|
||||||
*
|
*
|
||||||
* @param naturalIdValue The value of the natural-id for the entity to retrieve
|
* @param naturalIdValue The value of the natural-id
|
||||||
*
|
*
|
||||||
* @return The persistent instance or {@code null}
|
* @return The persistent instance or {@code null}
|
||||||
*/
|
*/
|
||||||
T load(Object naturalIdValue);
|
T load(Object naturalIdValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same semantic as {@link #load} except that here {@link Optional} is returned to
|
* Just like {@link #load}, except that here an {@link Optional}
|
||||||
* handle nullability.
|
* is returned.
|
||||||
*
|
*
|
||||||
* @param naturalIdValue The identifier
|
* @param naturalIdValue The identifier
|
||||||
*
|
*
|
||||||
* @return The persistent instance, if one, wrapped in Optional
|
* @return The persistent instance, if any, as an {@link Optional}
|
||||||
*/
|
*/
|
||||||
Optional<T> loadOptional(Object naturalIdValue);
|
Optional<T> loadOptional(Object naturalIdValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import jakarta.persistence.metamodel.SingularAttribute;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.NaturalIdLoadAccess;
|
import org.hibernate.NaturalIdLoadAccess;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
|
||||||
|
@ -31,6 +31,12 @@ public class NaturalIdLoadAccessImpl<T> extends BaseNaturalIdLoadAccessImpl<T> i
|
||||||
return (NaturalIdLoadAccessImpl<T>) super.with( lockOptions );
|
return (NaturalIdLoadAccessImpl<T>) super.with( lockOptions );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> NaturalIdLoadAccess<T> using(SingularAttribute<? super T, X> attribute, X value) {
|
||||||
|
naturalIdParameters.put( attribute.getName(), value );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NaturalIdLoadAccess<T> using(String attributeName, Object value) {
|
public NaturalIdLoadAccess<T> using(String attributeName, Object value) {
|
||||||
naturalIdParameters.put( attributeName, value );
|
naturalIdParameters.put( attributeName, value );
|
||||||
|
@ -38,6 +44,12 @@ public class NaturalIdLoadAccessImpl<T> extends BaseNaturalIdLoadAccessImpl<T> i
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public NaturalIdLoadAccess<T> using(Map<String, ?> mappings) {
|
||||||
|
naturalIdParameters.putAll( mappings );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override @Deprecated
|
||||||
public NaturalIdLoadAccess<T> using(Object... mappings) {
|
public NaturalIdLoadAccess<T> using(Object... mappings) {
|
||||||
CollectionHelper.collectMapEntries( naturalIdParameters::put, mappings );
|
CollectionHelper.collectMapEntries( naturalIdParameters::put, mappings );
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
package org.hibernate.orm.test.mapping.identifier;
|
package org.hibernate.orm.test.mapping.identifier;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.Embedded;
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
@ -67,6 +66,16 @@ public class MultipleNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
.load();
|
.load();
|
||||||
//end::naturalid-load-access-example[]
|
//end::naturalid-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
});
|
||||||
|
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||||
|
Publisher publisher = entityManager.getReference(Publisher.class, 1L);
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.byNaturalId(Book.class)
|
||||||
|
.using(Map.of("productNumber", "973022823X", "publisher", publisher))
|
||||||
|
.load();
|
||||||
|
|
||||||
assertEquals("High-Performance Java Persistence", book.getTitle());
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,8 +190,8 @@ public class CompoundNaturalIdTests {
|
||||||
final NaturalIdMultiLoadAccess<Account> loadAccess = session.byMultipleNaturalId( Account.class );
|
final NaturalIdMultiLoadAccess<Account> loadAccess = session.byMultipleNaturalId( Account.class );
|
||||||
loadAccess.enableOrderedReturn( false );
|
loadAccess.enableOrderedReturn( false );
|
||||||
final List<Account> accounts = loadAccess.multiLoad(
|
final List<Account> accounts = loadAccess.multiLoad(
|
||||||
NaturalIdMultiLoadAccess.compoundValue( "system", "matrix", "username", "neo" ),
|
Map.of( "system", "matrix", "username", "neo" ),
|
||||||
NaturalIdMultiLoadAccess.compoundValue( "system", "matrix", "username", "trinity" )
|
Map.of( "system", "matrix", "username", "trinity" )
|
||||||
);
|
);
|
||||||
assertThat( accounts.size(), is( 2 ) );
|
assertThat( accounts.size(), is( 2 ) );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue