diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/TableSet.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/TableSet.java new file mode 100644 index 0000000000..d248a3ba7a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/TableSet.java @@ -0,0 +1,84 @@ +/* + * 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.persister.entity.mutation; + +import java.util.Arrays; +import java.util.BitSet; + +import org.hibernate.sql.model.MutationTarget; +import org.hibernate.sql.model.TableMapping; + +/** + * Represents a Set of TableMapping(s); table mappings are + * identified by an ordered unique id: the order in which + * they are updated within the scope of a particular persister. + * This makes it possible to store a set of them as a bitset, + * which is typically more efficient than using a {@link java.util.Set}. + * These table ids come from {@link org.hibernate.sql.model.TableMapping#getRelativePosition}. + *

N.B. Make sure to not store TableMappings from different + * persisters, as their unique identifiers will overlap: + * we'll only verify a mismatch if assertions are enabled.

+ */ +public final class TableSet { + + private BitSet bits; + private Object[] checks; //Meant for assertions only + + public void add(final TableMapping tableMapping) { + if ( bits == null ) { + bits = new BitSet(); + } + assert addForChecks( tableMapping ); + bits.set( tableMapping.getRelativePosition() ); + } + + public boolean isEmpty() { + return bits == null; + } + + public boolean contains(final TableMapping tableMapping) { + assert matchRead( tableMapping ); + return bits != null && bits.get( tableMapping.getRelativePosition() ); + } + + //Meant for assertions only + private boolean matchRead(final TableMapping tableMapping) { + if ( bits != null ) { + final int index = tableMapping.getRelativePosition(); + if ( bits.get( index ) ) { + return checks[index] == tableMapping; + } + } + return true; //to make the assertion happy + } + + //Meant for assertions only + private boolean addForChecks(final TableMapping tableMapping) { + final int position = tableMapping.getRelativePosition(); + ensureCapacity( position ); + if ( checks[position] != null ) { + //pre-existing in the set: verify it's the same one. + if ( checks[position] != tableMapping ) { + return false;//fail the assertion + } + } + checks[position] = tableMapping; + return true; //to make the assertion happy + } + + //Meant for assertions only + private void ensureCapacity(final int position) { + final int increments = 3; //Needs to be at least 1. + if ( checks == null ) { + checks = new Object[position + increments]; + } + else if ( checks.length <= position ) { + checks = Arrays.copyOf( checks, position + increments ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java index 2cca6e7595..88c7322994 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java @@ -1242,10 +1242,10 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple private final int[] dirtyAttributeIndexes; private final InclusionChecker dirtinessChecker; - private final Set tablesNeedingUpdate = new HashSet<>(); - private final Set tablesNeedingDynamicUpdate = new HashSet<>(); - private final Set tablesWithNonNullValues = new HashSet<>(); - private final Set tablesWithPreviousNonNullValues = new HashSet<>(); + private final TableSet tablesNeedingUpdate = new TableSet(); + private final TableSet tablesNeedingDynamicUpdate = new TableSet(); + private final TableSet tablesWithNonNullValues = new TableSet(); + private final TableSet tablesWithPreviousNonNullValues = new TableSet(); private final List attributeAnalyses = new ArrayList<>(); @@ -1316,17 +1316,17 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple } @Override - public Set getTablesNeedingUpdate() { + public TableSet getTablesNeedingUpdate() { return tablesNeedingUpdate; } @Override - public Set getTablesWithNonNullValues() { + public TableSet getTablesWithNonNullValues() { return tablesWithNonNullValues; } @Override - public Set getTablesWithPreviousNonNullValues() { + public TableSet getTablesWithPreviousNonNullValues() { return tablesWithPreviousNonNullValues; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateValuesAnalysis.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateValuesAnalysis.java index ce95f1b517..9b5eff3533 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateValuesAnalysis.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateValuesAnalysis.java @@ -7,7 +7,6 @@ package org.hibernate.persister.entity.mutation; import java.util.List; -import java.util.Set; import org.hibernate.Incubating; import org.hibernate.sql.model.TableMapping; @@ -29,17 +28,17 @@ public interface UpdateValuesAnalysis extends ValuesAnalysis { * * @apiNote {@linkplain TableMapping#isInverse() Inverse tables} are not included in the result */ - Set getTablesNeedingUpdate(); + TableSet getTablesNeedingUpdate(); /** * Descriptor of the tables which had any non-null value bindings */ - Set getTablesWithNonNullValues(); + TableSet getTablesWithNonNullValues(); /** * Descriptor of the tables which had any non-null value bindings */ - Set getTablesWithPreviousNonNullValues(); + TableSet getTablesWithPreviousNonNullValues(); /** * Descriptors for the analysis of each attribute