From c56b6d7dc764109bc5559fd9a6e0d8d8d0c67026 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 19 Mar 2018 17:13:24 +0000 Subject: [PATCH] HHH-11867 - @UpdateTimestamp not working with @Inheritance( strategy = JOINED ) --- .../entity/AbstractEntityPersister.java | 56 +++++++---- .../tuple/entity/EntityMetamodel.java | 92 +------------------ 2 files changed, 42 insertions(+), 106 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 363d57a2a8..d7edee7a0a 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -187,7 +187,7 @@ public abstract class AbstractEntityPersister private final boolean[] propertyUniqueness; private final boolean[] propertySelectable; - private final List lobProperties = new ArrayList(); + private final List lobProperties = new ArrayList<>(); //information about lazy properties of this class private final String[] lazyPropertyNames; @@ -224,7 +224,7 @@ public abstract class AbstractEntityPersister // dynamic filters attached to the class-level private final FilterHelper filterHelper; - private final Set affectingFetchProfileNames = new HashSet(); + private final Set affectingFetchProfileNames = new HashSet<>(); private final Map uniqueKeyLoaders = new HashMap(); private final Map lockers = new HashMap(); @@ -1576,8 +1576,8 @@ public abstract class AbstractEntityPersister .toStatementString(); } - protected static interface InclusionChecker { - public boolean includeProperty(int propertyNumber); + protected interface InclusionChecker { + boolean includeProperty(int propertyNumber); } protected String concretePropertySelectFragment(String alias, final boolean[] includeProperty) { @@ -1675,7 +1675,7 @@ public abstract class AbstractEntityPersister // todo : cache this sql... String versionIncrementString = generateVersionIncrementUpdateString(); - PreparedStatement st = null; + PreparedStatement st; try { st = session .getJdbcCoordinator() @@ -3376,7 +3376,7 @@ public abstract class AbstractEntityPersister public void update( final Serializable id, final Object[] fields, - final int[] dirtyFields, + int[] dirtyFields, final boolean hasDirtyCollection, final Object[] oldFields, final Object oldVersion, @@ -3386,12 +3386,32 @@ public abstract class AbstractEntityPersister // apply any pre-update in-memory value generation if ( getEntityMetamodel().hasPreUpdateGeneratedValues() ) { - final InMemoryValueGenerationStrategy[] strategies = getEntityMetamodel().getInMemoryValueGenerationStrategies(); - for ( int i = 0; i < strategies.length; i++ ) { - if ( strategies[i] != null && strategies[i].getGenerationTiming().includesUpdate() ) { - fields[i] = strategies[i].getValueGenerator().generateValue( (Session) session, object ); - setPropertyValue( object, i, fields[i] ); - // todo : probably best to add to dirtyFields if not-null + final InMemoryValueGenerationStrategy[] valueGenerationStrategies = getEntityMetamodel().getInMemoryValueGenerationStrategies(); + int valueGenerationStrategiesSize = valueGenerationStrategies.length; + if ( valueGenerationStrategiesSize != 0 ) { + int[] fieldsPreUpdateNeeded = new int[valueGenerationStrategiesSize]; + for ( int i = 0; i < valueGenerationStrategiesSize; i++ ) { + if ( valueGenerationStrategies[i] != null && valueGenerationStrategies[i].getGenerationTiming() + .includesUpdate() ) { + fields[i] = valueGenerationStrategies[i].getValueGenerator().generateValue( + (Session) session, + object + ); + setPropertyValue( object, i, fields[i] ); + fieldsPreUpdateNeeded[i] = i; + } + } +// if ( fieldsPreUpdateNeeded.length != 0 ) { +// if ( dirtyFields != null ) { +// dirtyFields = ArrayHelper.join( fieldsPreUpdateNeeded, dirtyFields ); +// } +// else if ( hasDirtyCollection ) { +// dirtyFields = fieldsPreUpdateNeeded; +// } +// // no dirty fields and no dirty collections so no update needed ??? +// } + if ( fieldsPreUpdateNeeded.length != 0 && dirtyFields != null ) { + dirtyFields = ArrayHelper.join( fieldsPreUpdateNeeded, dirtyFields ); } } } @@ -3674,7 +3694,7 @@ public abstract class AbstractEntityPersister alias, innerJoin, includeSubclasses, - Collections.emptySet() + Collections.emptySet() ).toFromFragmentString(); } @@ -3699,7 +3719,7 @@ public abstract class AbstractEntityPersister alias, innerJoin, includeSubclasses, - Collections.emptySet() + Collections.emptySet() ).toWhereFragmentString(); } @@ -5380,7 +5400,6 @@ public abstract class AbstractEntityPersister // EntityDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private EntityIdentifierDefinition entityIdentifierDefinition; - private Iterable embeddedCompositeIdentifierAttributes; private Iterable attributeDefinitions; @Override @@ -5405,8 +5424,7 @@ public abstract class AbstractEntityPersister } public String[][] getPolymorphicJoinColumns(String lhsTableAlias, String propertyPath) { - Set subclassEntityNames = (Set) getEntityMetamodel() - .getSubclassEntityNames(); + Set subclassEntityNames = getEntityMetamodel().getSubclassEntityNames(); // We will collect all the join columns from the LHS subtypes here List polymorphicJoinColumns = new ArrayList<>( subclassEntityNames.size() ); @@ -5522,7 +5540,7 @@ public abstract class AbstractEntityPersister // to try and drive SQL generation on these (which we do ultimately). A possible solution there // would be to delay all SQL generation until postInstantiate - Map attributeDefinitionsByName = new LinkedHashMap(); + Map attributeDefinitionsByName = new LinkedHashMap<>(); collectAttributeDefinitions( attributeDefinitionsByName, getEntityMetamodel() ); @@ -5542,7 +5560,7 @@ public abstract class AbstractEntityPersister // } this.attributeDefinitions = Collections.unmodifiableList( - new ArrayList( attributeDefinitionsByName.values() ) + new ArrayList<>( attributeDefinitionsByName.values() ) ); // // todo : leverage the attribute definitions housed on EntityMetamodel // // for that to work, we'd have to be able to walk our super entity persister(s) diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index e7854c6cf1..98d34aba73 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -24,7 +24,6 @@ import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.ValueInclusion; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.ArrayHelper; @@ -92,7 +91,7 @@ public class EntityMetamodel implements Serializable { private final InDatabaseValueGenerationStrategy[] inDatabaseValueGenerationStrategies; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private final Map propertyIndexes = new HashMap(); + private final Map propertyIndexes = new HashMap<>(); private final boolean hasCollections; private final boolean hasMutableProperties; private final boolean hasLazyProperties; @@ -150,7 +149,7 @@ public class EntityMetamodel implements Serializable { propertySpan = persistentClass.getPropertyClosureSpan(); properties = new NonIdentifierAttribute[propertySpan]; - List naturalIdNumbers = new ArrayList(); + List naturalIdNumbers = new ArrayList<>(); // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ propertyNames = new String[propertySpan]; propertyTypes = new Type[propertySpan]; @@ -181,8 +180,6 @@ public class EntityMetamodel implements Serializable { boolean foundCollection = false; boolean foundMutable = false; boolean foundNonIdentifierPropertyNamedId = false; - boolean foundInsertGeneratedValue = false; - boolean foundUpdateGeneratedValue = false; boolean foundUpdateableNaturalIdProperty = false; while ( iter.hasNext() ) { @@ -379,7 +376,7 @@ public class EntityMetamodel implements Serializable { } entityMode = persistentClass.hasPojoRepresentation() ? EntityMode.POJO : EntityMode.MAP; - final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory(); + final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSessionFactoryOptions().getEntityTuplizerFactory(); final String tuplizerClassName = persistentClass.getTuplizerImplClassName( entityMode ); if ( tuplizerClassName == null ) { entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, persistentClass ); @@ -514,10 +511,6 @@ public class EntityMetamodel implements Serializable { public ValueGenerationStrategyException(String message) { super( message ); } - - public ValueGenerationStrategyException(String message, Throwable cause) { - super( message, cause ); - } } private static class CompositeGenerationStrategyPairBuilder { @@ -540,7 +533,7 @@ public class EntityMetamodel implements Serializable { private void add(InMemoryValueGenerationStrategy inMemoryStrategy) { if ( inMemoryStrategies == null ) { - inMemoryStrategies = new ArrayList(); + inMemoryStrategies = new ArrayList<>(); } inMemoryStrategies.add( inMemoryStrategy ); @@ -551,7 +544,7 @@ public class EntityMetamodel implements Serializable { private void add(InDatabaseValueGenerationStrategy inDatabaseStrategy) { if ( inDatabaseStrategies == null ) { - inDatabaseStrategies = new ArrayList(); + inDatabaseStrategies = new ArrayList<>(); } inDatabaseStrategies.add( inDatabaseStrategy ); @@ -730,81 +723,6 @@ public class EntityMetamodel implements Serializable { } } - private ValueInclusion determineInsertValueGenerationType(Property mappingProperty, NonIdentifierAttribute runtimeProperty) { - if ( isInsertGenerated( runtimeProperty ) ) { - return ValueInclusion.FULL; - } - else if ( mappingProperty.getValue() instanceof Component ) { - if ( hasPartialInsertComponentGeneration( ( Component ) mappingProperty.getValue() ) ) { - return ValueInclusion.PARTIAL; - } - } - return ValueInclusion.NONE; - } - - private boolean isInsertGenerated(NonIdentifierAttribute property) { - return property.getValueGenerationStrategy() != null - && property.getValueGenerationStrategy().getGenerationTiming() != GenerationTiming.NEVER; - } - - private boolean isInsertGenerated(Property property) { - return property.getValueGenerationStrategy() != null - && property.getValueGenerationStrategy().getGenerationTiming() != GenerationTiming.NEVER; - } - - private boolean hasPartialInsertComponentGeneration(Component component) { - Iterator subProperties = component.getPropertyIterator(); - while ( subProperties.hasNext() ) { - final Property prop = ( Property ) subProperties.next(); - if ( isInsertGenerated( prop ) ) { - return true; - } - else if ( prop.getValue() instanceof Component ) { - if ( hasPartialInsertComponentGeneration( (Component) prop.getValue() ) ) { - return true; - } - } - } - return false; - } - - private ValueInclusion determineUpdateValueGenerationType(Property mappingProperty, NonIdentifierAttribute runtimeProperty) { - if ( isUpdateGenerated( runtimeProperty ) ) { - return ValueInclusion.FULL; - } - else if ( mappingProperty.getValue() instanceof Component ) { - if ( hasPartialUpdateComponentGeneration( ( Component ) mappingProperty.getValue() ) ) { - return ValueInclusion.PARTIAL; - } - } - return ValueInclusion.NONE; - } - - private static boolean isUpdateGenerated(Property property) { - return property.getValueGenerationStrategy() != null - && property.getValueGenerationStrategy().getGenerationTiming() == GenerationTiming.ALWAYS; - } - - private static boolean isUpdateGenerated(NonIdentifierAttribute property) { - return property.getValueGenerationStrategy() != null - && property.getValueGenerationStrategy().getGenerationTiming() == GenerationTiming.ALWAYS; - } - - private boolean hasPartialUpdateComponentGeneration(Component component) { - Iterator subProperties = component.getPropertyIterator(); - while ( subProperties.hasNext() ) { - Property prop = (Property) subProperties.next(); - if ( isUpdateGenerated( prop ) ) { - return true; - } - else if ( prop.getValue() instanceof Component ) { - if ( hasPartialUpdateComponentGeneration( ( Component ) prop.getValue() ) ) { - return true; - } - } - } - return false; - } private void mapPropertyToIndex(Property prop, int i) { propertyIndexes.put( prop.getName(), i );