HHH-16079 rewrite javadoc relating to query spaces + add @Synchronize(logical=false)
This commit is contained in:
parent
75f3f699b5
commit
662594fd5f
|
@ -156,10 +156,12 @@ public @interface NamedNativeQuery {
|
|||
boolean readOnly() default false;
|
||||
|
||||
/**
|
||||
* The query spaces involved in this query.
|
||||
* The {@linkplain org.hibernate.query.SynchronizeableQuery query spaces}
|
||||
* involved in this query.
|
||||
*
|
||||
* @see org.hibernate.query.SynchronizeableQuery
|
||||
* @see org.hibernate.jpa.HibernateHints#HINT_NATIVE_SPACES
|
||||
* @see Synchronize
|
||||
*/
|
||||
String[] querySpaces() default {};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ public @interface NamedQuery {
|
|||
*
|
||||
* @see org.hibernate.query.CommonQueryContract#setTimeout(int)
|
||||
* @see org.hibernate.jpa.HibernateHints#HINT_TIMEOUT
|
||||
* @see import org.hibernate.jpa.SpecHints#HINT_SPEC_QUERY_TIMEOUT
|
||||
* @see org.hibernate.jpa.SpecHints#HINT_SPEC_QUERY_TIMEOUT
|
||||
*/
|
||||
int timeout() default -1;
|
||||
|
||||
|
|
|
@ -13,22 +13,47 @@ import static java.lang.annotation.ElementType.TYPE;
|
|||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Specifies the tables that hold state mapped by the annotated derived
|
||||
* entity, ensuring that auto-flush happens correctly and that queries
|
||||
* against the derived entity do not return stale data.
|
||||
* Specifies the tables that hold state mapped by the annotated entity.
|
||||
* <p>
|
||||
* This annotation may be used in combination with {@link Subselect}, or
|
||||
* when an entity maps a database view.
|
||||
*
|
||||
* If Hibernate is not aware of that a certain table holds state mapped
|
||||
* by an entity class, then {@linkplain org.hibernate.FlushMode#AUTO
|
||||
* auto-flush} might not occur when it should, and queries against the
|
||||
* entity might return stale data.
|
||||
* <p>
|
||||
* This annotation might be necessary if:
|
||||
* <ul>
|
||||
* <li>the entity maps a database view,
|
||||
* <li>the entity is persisted using handwritten SQL, that is, using
|
||||
* {@link SQLSelect @SQLSelect} and friends.
|
||||
* <li>the entity is mapped using {@link Subselect @Subselect}.
|
||||
* </ul>
|
||||
* <p>
|
||||
* By default, the table names specified by this annotation are interpreted
|
||||
* as {@linkplain org.hibernate.boot.model.naming.PhysicalNamingStrategy
|
||||
* logical names}, and are processed by
|
||||
* {@link org.hibernate.boot.model.naming.PhysicalNamingStrategy#toPhysicalTableName}.
|
||||
* But if {@link #logical logical=false}, the table names will be treated
|
||||
* as physical names, and will not be processed by the naming strategy.
|
||||
*
|
||||
* @author Sharath Reddy
|
||||
*
|
||||
* @see org.hibernate.query.SynchronizeableQuery
|
||||
*/
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Synchronize {
|
||||
/**
|
||||
* Names of tables that hold state mapped by the derived entity.
|
||||
* Names of tables that hold state mapped by the annotated entity.
|
||||
* Updates to these tables must be flushed to the database before
|
||||
* the derived entity is queried.
|
||||
* execution of any query which refers to the annotated entity.
|
||||
*/
|
||||
String[] value();
|
||||
|
||||
/**
|
||||
* Specifies whether the table names given by {@link #value}
|
||||
* should be interpreted as logical or physical names.
|
||||
*
|
||||
* @return {@code true} if they are logical names
|
||||
*/
|
||||
boolean logical() default true;
|
||||
}
|
||||
|
|
|
@ -1336,17 +1336,23 @@ public class EntityBinder {
|
|||
private void bindSynchronize() {
|
||||
if ( annotatedClass.isAnnotationPresent( Synchronize.class ) ) {
|
||||
final JdbcEnvironment jdbcEnvironment = context.getMetadataCollector().getDatabase().getJdbcEnvironment();
|
||||
for ( String table : annotatedClass.getAnnotation(Synchronize.class).value() ) {
|
||||
persistentClass.addSynchronizedTable(
|
||||
context.getBuildingOptions().getPhysicalNamingStrategy().toPhysicalTableName(
|
||||
jdbcEnvironment.getIdentifierHelper().toIdentifier( table ),
|
||||
jdbcEnvironment
|
||||
).render( jdbcEnvironment.getDialect() )
|
||||
);
|
||||
final Synchronize synchronize = annotatedClass.getAnnotation(Synchronize.class);
|
||||
for ( String table : synchronize.value() ) {
|
||||
String physicalName = synchronize.logical() ? toPhysicalName( jdbcEnvironment, table ) : table;
|
||||
persistentClass.addSynchronizedTable( physicalName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String toPhysicalName(JdbcEnvironment jdbcEnvironment, String logicalName) {
|
||||
return context.getBuildingOptions().getPhysicalNamingStrategy()
|
||||
.toPhysicalTableName(
|
||||
jdbcEnvironment.getIdentifierHelper().toIdentifier( logicalName ),
|
||||
jdbcEnvironment
|
||||
)
|
||||
.render( jdbcEnvironment.getDialect() );
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private void bindCustomPersister() {
|
||||
//set persister if needed
|
||||
|
|
|
@ -6,32 +6,32 @@
|
|||
*/
|
||||
package org.hibernate.jpa;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
/**
|
||||
* List of Hibernate-specific (extension) hints available to query,
|
||||
* load and lock scenarios.
|
||||
* load, and lock scenarios.
|
||||
* <p>
|
||||
* Some hints are only effective in certain scenarios, which is noted on
|
||||
* each constant's documentation.
|
||||
* Some hints are only effective in certain scenarios, which is noted
|
||||
* on each constant's documentation.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface HibernateHints {
|
||||
/**
|
||||
* Hint for specifying the {@link org.hibernate.FlushMode}
|
||||
* to apply to an EntityManager or a Query
|
||||
* Hint for specifying the {@link org.hibernate.FlushMode} to
|
||||
* apply to an {@link jakarta.persistence.EntityManager} or
|
||||
* {@link jakarta.persistence.Query}.
|
||||
*
|
||||
* @see Query#setHibernateFlushMode
|
||||
* @see org.hibernate.query.Query#setHibernateFlushMode
|
||||
* @see org.hibernate.Session#setHibernateFlushMode
|
||||
*/
|
||||
String HINT_FLUSH_MODE = "org.hibernate.flushMode";
|
||||
|
||||
/**
|
||||
* Hint for specifying a Query timeout, in seconds.
|
||||
* Hint for specifying a
|
||||
* {@linkplain org.hibernate.query.CommonQueryContract#setTimeout
|
||||
* query timeout}, in seconds.
|
||||
*
|
||||
* @see org.hibernate.query.Query#setTimeout
|
||||
* @see org.hibernate.query.CommonQueryContract#setTimeout
|
||||
* @see java.sql.Statement#setQueryTimeout
|
||||
* @see SpecHints#HINT_SPEC_QUERY_TIMEOUT
|
||||
*/
|
||||
|
@ -40,67 +40,69 @@ public interface HibernateHints {
|
|||
/**
|
||||
* Hint for specifying that objects loaded into the persistence
|
||||
* context as a result of a query should be associated with the
|
||||
* persistence context as read-only.
|
||||
* persistence context in
|
||||
* {@linkplain org.hibernate.query.SelectionQuery#setReadOnly
|
||||
* read-only mode}.
|
||||
*
|
||||
* @see Query#setReadOnly
|
||||
* @see org.hibernate.query.SelectionQuery#setReadOnly
|
||||
* @see org.hibernate.Session#setDefaultReadOnly
|
||||
*/
|
||||
String HINT_READ_ONLY = "org.hibernate.readOnly";
|
||||
|
||||
/**
|
||||
* Hint for specifying a fetch size to be applied to the
|
||||
* JDBC statement.
|
||||
* Hint for specifying a JDBC fetch size to be applied to the
|
||||
* statement.
|
||||
*
|
||||
* @see Query#setFetchSize
|
||||
* @see org.hibernate.query.SelectionQuery#setFetchSize
|
||||
* @see java.sql.Statement#setFetchSize
|
||||
*/
|
||||
String HINT_FETCH_SIZE = "org.hibernate.fetchSize";
|
||||
|
||||
/**
|
||||
* Hint for specifying whether results from a query should
|
||||
* be stored in the query cache
|
||||
* Hint for specifying whether results from a query should be
|
||||
* stored in the query cache.
|
||||
*
|
||||
* @see Query#setCacheable
|
||||
* @see org.hibernate.query.SelectionQuery#setCacheable
|
||||
*/
|
||||
String HINT_CACHEABLE = "org.hibernate.cacheable";
|
||||
|
||||
/**
|
||||
* Hint for specifying the region of the query cache into which
|
||||
* the results should be stored
|
||||
* the results should be stored.
|
||||
*
|
||||
* @implSpec No effect unless {@link #HINT_CACHEABLE} is set to {@code true}
|
||||
*
|
||||
* @see Query#setCacheRegion
|
||||
* @see org.hibernate.query.SelectionQuery#setCacheRegion
|
||||
*/
|
||||
String HINT_CACHE_REGION = "org.hibernate.cacheRegion";
|
||||
|
||||
/**
|
||||
* Hint for specifying the {@link org.hibernate.CacheMode} to use
|
||||
* Hint for specifying the {@link org.hibernate.CacheMode} to use.
|
||||
*
|
||||
* @implSpec No effect unless {@link #HINT_CACHEABLE} is set to {@code true}
|
||||
*
|
||||
* @see Query#setCacheMode
|
||||
* @see org.hibernate.query.SelectionQuery#setCacheMode
|
||||
*/
|
||||
String HINT_CACHE_MODE = "org.hibernate.cacheMode";
|
||||
|
||||
/**
|
||||
* Hint for specifying a database comment to be applied to
|
||||
* the SQL sent to the database.
|
||||
* Hint for specifying a database comment to be appended to the
|
||||
* SQL statement sent to the database.
|
||||
*
|
||||
* @implSpec Not valid for {@link org.hibernate.procedure.ProcedureCall}
|
||||
* nor {@link jakarta.persistence.StoredProcedureQuery} scenarios
|
||||
* @implSpec Not valid for {@link org.hibernate.procedure.ProcedureCall},
|
||||
* nor for {@link jakarta.persistence.StoredProcedureQuery}.
|
||||
*
|
||||
* @see Query#setComment
|
||||
* @see org.hibernate.query.SelectionQuery#setComment
|
||||
*/
|
||||
String HINT_COMMENT = "org.hibernate.comment";
|
||||
|
||||
/**
|
||||
* Hint to enable/disable the follow-on-locking mechanism provided by
|
||||
* {@link org.hibernate.dialect.Dialect#useFollowOnLocking}.
|
||||
* Hint to enable or disable the follow-on locking mechanism provided
|
||||
* by {@link org.hibernate.dialect.Dialect#useFollowOnLocking}.
|
||||
* <p>
|
||||
* A value of {@code true} enables follow-on-locking, whereas a value of
|
||||
* {@code false} disables it. If the value is {@code null}, the
|
||||
* {@code Dialect}'s default strategy is used.
|
||||
* A value of {@code true} enables follow-on-locking, whereas a value
|
||||
* of {@code false} disables it. If the value is {@code null}, the
|
||||
* dialect itself will determine whether follow-on locking is used.
|
||||
*
|
||||
* @see org.hibernate.LockOptions#setFollowOnLocking(Boolean)
|
||||
*
|
||||
|
@ -112,38 +114,38 @@ public interface HibernateHints {
|
|||
* Hint for specifying the lock mode to apply to the results of a
|
||||
* native query.
|
||||
* <p>
|
||||
* While Hibernate supports applying lock-mode to a native-query, the
|
||||
* JPA specification requires that {@link jakarta.persistence.Query#setLockMode}
|
||||
* throw an {@link IllegalStateException} if called for a native query.
|
||||
* <p>
|
||||
* Accepts a {@link jakarta.persistence.LockModeType} or a {@link org.hibernate.LockMode}
|
||||
* Accepts either a {@link jakarta.persistence.LockModeType} or a
|
||||
* {@link org.hibernate.LockMode}.
|
||||
*
|
||||
* @apiNote While Hibernate supports applying a lock mode to a
|
||||
* native query, the JPA specification requires that
|
||||
* {@link jakarta.persistence.Query#setLockMode} throw
|
||||
* an {@link IllegalStateException} in this scenario.
|
||||
*/
|
||||
String HINT_NATIVE_LOCK_MODE = "org.hibernate.lockMode";
|
||||
|
||||
/**
|
||||
* Hint for specifying query spaces to be applied to a native query.
|
||||
* Hint for specifying the
|
||||
* {@link org.hibernate.query.SynchronizeableQuery query spaces}
|
||||
* that affect the results of a native query.
|
||||
* <p>
|
||||
* Passed value can be any of:<ul>
|
||||
* <li>List of the spaces</li>
|
||||
* <li>array of the spaces</li>
|
||||
* <li>String as "whitespace"-separated list of the spaces</li>
|
||||
* Passed value can be any of:
|
||||
* <ul>
|
||||
* <li>a {@link org.hibernate.mapping.List} of the spaces,
|
||||
* <li>an array of the spaces, or
|
||||
* <li>a string with a whitespace-separated list of the spaces.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Note that the passed space need not match any real spaces/tables in
|
||||
* the underlying query. This can be used to completely circumvent
|
||||
* the auto-flush checks as well as any cache invalidation that might
|
||||
* occur as part of a flush. See {@link org.hibernate.query.SynchronizeableQuery}
|
||||
* and {@link FlushMode#MANUAL} for more information.
|
||||
*
|
||||
* @see org.hibernate.query.SynchronizeableQuery
|
||||
* @see #HINT_FLUSH_MODE
|
||||
* @see org.hibernate.annotations.NamedNativeQuery#querySpaces
|
||||
*/
|
||||
String HINT_NATIVE_SPACES = "org.hibernate.query.native.spaces";
|
||||
|
||||
/**
|
||||
* Whether to treat a {@link org.hibernate.procedure.ProcedureCall}
|
||||
* or {@link jakarta.persistence.StoredProcedureQuery} as a call
|
||||
* to a function rather than a call to a procedure
|
||||
* to a function rather than a call to a procedure.
|
||||
*/
|
||||
String HINT_CALLABLE_FUNCTION = "org.hibernate.callableFunction";
|
||||
}
|
||||
|
|
|
@ -12,16 +12,41 @@ import java.util.Collection;
|
|||
import org.hibernate.MappingException;
|
||||
|
||||
/**
|
||||
* A unifying interface for queries which can define tables (query spaces) to synchronize on.
|
||||
* Represents the abstract notion of a query whose results are affected by the data stored
|
||||
* in a given set of named <em>query spaces</em>. A query space is usually, but not always,
|
||||
* a relational database table, in which case the name of the space is simply the table name.
|
||||
* <p>
|
||||
* These query spaces affect the process of auto-flushing by determining which entities will be
|
||||
* processed by auto-flush based on the table to which those entities are mapped and which are
|
||||
* determined to have pending state changes.
|
||||
* Each {@linkplain jakarta.persistence.Entity entity type} is understood to store its state
|
||||
* in one or more query spaces. Usually, the query spaces are automatically determined by
|
||||
* the mapping, but sometimes they must be specified explicitly using
|
||||
* {@link org.hibernate.annotations.Synchronize @Synchronize}.
|
||||
* <p>
|
||||
* In a similar manner, these query spaces also affect how query result caching can recognize
|
||||
* invalidated results.
|
||||
* Query spaces mediate the interaction between query execution and synchronization of
|
||||
* in-memory state with the database:
|
||||
* <ul>
|
||||
* <li>
|
||||
* When {@linkplain org.hibernate.FlushMode#AUTO auto-flush} is enabled, in-memory changes
|
||||
* to every dirty entity whose state belongs to any query space which affects a given query
|
||||
* must be flushed before the query is executed.
|
||||
* <li>
|
||||
* Conversely, when changes to an entity whose state is stored in a given query space are
|
||||
* flushed to the database, every {@linkplain SelectionQuery#setCacheable cached query
|
||||
* result set} for a query affected by that query space must be immediately invalidated.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Typically, query spaces are independent (non-overlapping), and Hibernate always treats
|
||||
* them as such. Overlapping or hierarchical query spaces are in principle meaningful, but
|
||||
* any such relationship between query spaces is the responsibility of the client.
|
||||
* <p>
|
||||
* A query space name is not always a table name. In principle, it's permitted to be any
|
||||
* arbitrary string which uniquely identifies an abstract location where state is stored
|
||||
* persistently. It's even possible that the data in a single table is segmented in such
|
||||
* a way that the table is effectively the union of multiple independent query spaces.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see org.hibernate.annotations.Synchronize
|
||||
* @see org.hibernate.jpa.HibernateHints#HINT_NATIVE_SPACES
|
||||
*/
|
||||
public interface SynchronizeableQuery {
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue