Skip to content

Commit

Permalink
HHH-16089 allow @synchronize for a collection
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinking committed Jan 24, 2023
1 parent 4a37bf8 commit 204970a
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,28 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Specifies the tables that hold state mapped by the annotated entity.
* Specifies a table or tables that hold state mapped by the annotated
* entity or collection.
* <p>
* If Hibernate is not aware 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.
* by an entity class or collection, then modifications might not be
* {@linkplain org.hibernate.FlushMode#AUTO automatically synchronized}
* with the database before a query is executed against that table, and
* the query might return stale data.
* <p>
* This annotation might be necessary if:
* Ordinarily, Hibernate knows the tables containing the state of an
* entity or collection. 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, or
* <li>the entity is mapped using {@link Subselect @Subselect}.
* <li>an entity or collection maps a database view,
* <li>an entity or collection is persisted using handwritten SQL,
* that is, using {@link SQLSelect @SQLSelect} and friends, or
* <li>an entity is mapped using {@link Subselect @Subselect}.
* </ul>
* <p>
* By default, the table names specified by this annotation are interpreted
Expand All @@ -39,7 +44,7 @@
*
* @see org.hibernate.query.SynchronizeableQuery
*/
@Target(TYPE)
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Synchronize {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.hibernate.annotations.SQLUpdate;
import org.hibernate.annotations.SortComparator;
import org.hibernate.annotations.SortNatural;
import org.hibernate.annotations.Synchronize;
import org.hibernate.annotations.Where;
import org.hibernate.annotations.WhereJoinTable;
import org.hibernate.annotations.common.reflection.ReflectionManager;
Expand All @@ -83,6 +84,7 @@
import org.hibernate.boot.spi.PropertyData;
import org.hibernate.boot.spi.SecondPass;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.CollectionHelper;
Expand Down Expand Up @@ -1642,6 +1644,7 @@ protected void bindOneToManySecondPass(Map<String, PersistentClass> persistentCl
LOG.debugf( "Mapping collection: %s -> %s", collection.getRole(), collection.getCollectionTable().getName() );
}

bindSynchronize();
bindFilters( false );
handleWhere( false );

Expand Down Expand Up @@ -1681,6 +1684,26 @@ private void handleJpaOrderBy(Collection collection, PersistentClass associatedC
}
}

private void bindSynchronize() {
if ( property.isAnnotationPresent( Synchronize.class ) ) {
final JdbcEnvironment jdbcEnvironment = buildingContext.getMetadataCollector().getDatabase().getJdbcEnvironment();
final Synchronize synchronize = property.getAnnotation(Synchronize.class);
for ( String table : synchronize.value() ) {
String physicalName = synchronize.logical() ? toPhysicalName( jdbcEnvironment, table ) : table;
collection.addSynchronizedTable( physicalName );
}
}
}

private String toPhysicalName(JdbcEnvironment jdbcEnvironment, String logicalName) {
return buildingContext.getBuildingOptions().getPhysicalNamingStrategy()
.toPhysicalTableName(
jdbcEnvironment.getIdentifierHelper().toIdentifier( logicalName ),
jdbcEnvironment
)
.render( jdbcEnvironment.getDialect() );
}

private void bindFilters(boolean hasAssociationTable) {
final Filter simpleFilter = property.getAnnotation( Filter.class );
//set filtering
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,10 @@ public java.util.Set<String> getSynchronizedTables() {
return synchronizedTables;
}

public void addSynchronizedTable(String table) {
synchronizedTables.add( table );
}

public String getLoaderName() {
return loaderName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
* 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>
* 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
* Each {@linkplain jakarta.persistence.Entity entity type} or collection 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>
* Query spaces mediate the interaction between query execution and synchronization of
Expand Down

0 comments on commit 204970a

Please sign in to comment.