HHH-11867 - @UpdateTimestamp not working with @Inheritance( strategy = JOINED )

This commit is contained in:
Andrea Boriero 2018-03-19 17:13:24 +00:00
parent 2ad8b3540a
commit c56b6d7dc7
2 changed files with 42 additions and 106 deletions

View File

@ -187,7 +187,7 @@ public abstract class AbstractEntityPersister
private final boolean[] propertyUniqueness; private final boolean[] propertyUniqueness;
private final boolean[] propertySelectable; private final boolean[] propertySelectable;
private final List<Integer> lobProperties = new ArrayList<Integer>(); private final List<Integer> lobProperties = new ArrayList<>();
//information about lazy properties of this class //information about lazy properties of this class
private final String[] lazyPropertyNames; private final String[] lazyPropertyNames;
@ -224,7 +224,7 @@ public abstract class AbstractEntityPersister
// dynamic filters attached to the class-level // dynamic filters attached to the class-level
private final FilterHelper filterHelper; private final FilterHelper filterHelper;
private final Set<String> affectingFetchProfileNames = new HashSet<String>(); private final Set<String> affectingFetchProfileNames = new HashSet<>();
private final Map uniqueKeyLoaders = new HashMap(); private final Map uniqueKeyLoaders = new HashMap();
private final Map lockers = new HashMap(); private final Map lockers = new HashMap();
@ -1576,8 +1576,8 @@ public abstract class AbstractEntityPersister
.toStatementString(); .toStatementString();
} }
protected static interface InclusionChecker { protected interface InclusionChecker {
public boolean includeProperty(int propertyNumber); boolean includeProperty(int propertyNumber);
} }
protected String concretePropertySelectFragment(String alias, final boolean[] includeProperty) { protected String concretePropertySelectFragment(String alias, final boolean[] includeProperty) {
@ -1675,7 +1675,7 @@ public abstract class AbstractEntityPersister
// todo : cache this sql... // todo : cache this sql...
String versionIncrementString = generateVersionIncrementUpdateString(); String versionIncrementString = generateVersionIncrementUpdateString();
PreparedStatement st = null; PreparedStatement st;
try { try {
st = session st = session
.getJdbcCoordinator() .getJdbcCoordinator()
@ -3376,7 +3376,7 @@ public abstract class AbstractEntityPersister
public void update( public void update(
final Serializable id, final Serializable id,
final Object[] fields, final Object[] fields,
final int[] dirtyFields, int[] dirtyFields,
final boolean hasDirtyCollection, final boolean hasDirtyCollection,
final Object[] oldFields, final Object[] oldFields,
final Object oldVersion, final Object oldVersion,
@ -3386,12 +3386,32 @@ public abstract class AbstractEntityPersister
// apply any pre-update in-memory value generation // apply any pre-update in-memory value generation
if ( getEntityMetamodel().hasPreUpdateGeneratedValues() ) { if ( getEntityMetamodel().hasPreUpdateGeneratedValues() ) {
final InMemoryValueGenerationStrategy[] strategies = getEntityMetamodel().getInMemoryValueGenerationStrategies(); final InMemoryValueGenerationStrategy[] valueGenerationStrategies = getEntityMetamodel().getInMemoryValueGenerationStrategies();
for ( int i = 0; i < strategies.length; i++ ) { int valueGenerationStrategiesSize = valueGenerationStrategies.length;
if ( strategies[i] != null && strategies[i].getGenerationTiming().includesUpdate() ) { if ( valueGenerationStrategiesSize != 0 ) {
fields[i] = strategies[i].getValueGenerator().generateValue( (Session) session, object ); int[] fieldsPreUpdateNeeded = new int[valueGenerationStrategiesSize];
setPropertyValue( object, i, fields[i] ); for ( int i = 0; i < valueGenerationStrategiesSize; i++ ) {
// todo : probably best to add to dirtyFields if not-null 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, alias,
innerJoin, innerJoin,
includeSubclasses, includeSubclasses,
Collections.<String>emptySet() Collections.emptySet()
).toFromFragmentString(); ).toFromFragmentString();
} }
@ -3699,7 +3719,7 @@ public abstract class AbstractEntityPersister
alias, alias,
innerJoin, innerJoin,
includeSubclasses, includeSubclasses,
Collections.<String>emptySet() Collections.emptySet()
).toWhereFragmentString(); ).toWhereFragmentString();
} }
@ -5380,7 +5400,6 @@ public abstract class AbstractEntityPersister
// EntityDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EntityDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private EntityIdentifierDefinition entityIdentifierDefinition; private EntityIdentifierDefinition entityIdentifierDefinition;
private Iterable<AttributeDefinition> embeddedCompositeIdentifierAttributes;
private Iterable<AttributeDefinition> attributeDefinitions; private Iterable<AttributeDefinition> attributeDefinitions;
@Override @Override
@ -5405,8 +5424,7 @@ public abstract class AbstractEntityPersister
} }
public String[][] getPolymorphicJoinColumns(String lhsTableAlias, String propertyPath) { public String[][] getPolymorphicJoinColumns(String lhsTableAlias, String propertyPath) {
Set<String> subclassEntityNames = (Set<String>) getEntityMetamodel() Set<String> subclassEntityNames = getEntityMetamodel().getSubclassEntityNames();
.getSubclassEntityNames();
// We will collect all the join columns from the LHS subtypes here // We will collect all the join columns from the LHS subtypes here
List<String[]> polymorphicJoinColumns = new ArrayList<>( subclassEntityNames.size() ); List<String[]> 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 // 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 // would be to delay all SQL generation until postInstantiate
Map<String, AttributeDefinition> attributeDefinitionsByName = new LinkedHashMap<String, AttributeDefinition>(); Map<String, AttributeDefinition> attributeDefinitionsByName = new LinkedHashMap<>();
collectAttributeDefinitions( attributeDefinitionsByName, getEntityMetamodel() ); collectAttributeDefinitions( attributeDefinitionsByName, getEntityMetamodel() );
@ -5542,7 +5560,7 @@ public abstract class AbstractEntityPersister
// } // }
this.attributeDefinitions = Collections.unmodifiableList( this.attributeDefinitions = Collections.unmodifiableList(
new ArrayList<AttributeDefinition>( attributeDefinitionsByName.values() ) new ArrayList<>( attributeDefinitionsByName.values() )
); );
// // todo : leverage the attribute definitions housed on EntityMetamodel // // 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) // // for that to work, we'd have to be able to walk our super entity persister(s)

View File

@ -24,7 +24,6 @@ import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.ValueInclusion;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
@ -92,7 +91,7 @@ public class EntityMetamodel implements Serializable {
private final InDatabaseValueGenerationStrategy[] inDatabaseValueGenerationStrategies; private final InDatabaseValueGenerationStrategy[] inDatabaseValueGenerationStrategies;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private final Map<String, Integer> propertyIndexes = new HashMap<String, Integer>(); private final Map<String, Integer> propertyIndexes = new HashMap<>();
private final boolean hasCollections; private final boolean hasCollections;
private final boolean hasMutableProperties; private final boolean hasMutableProperties;
private final boolean hasLazyProperties; private final boolean hasLazyProperties;
@ -150,7 +149,7 @@ public class EntityMetamodel implements Serializable {
propertySpan = persistentClass.getPropertyClosureSpan(); propertySpan = persistentClass.getPropertyClosureSpan();
properties = new NonIdentifierAttribute[propertySpan]; properties = new NonIdentifierAttribute[propertySpan];
List<Integer> naturalIdNumbers = new ArrayList<Integer>(); List<Integer> naturalIdNumbers = new ArrayList<>();
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
propertyNames = new String[propertySpan]; propertyNames = new String[propertySpan];
propertyTypes = new Type[propertySpan]; propertyTypes = new Type[propertySpan];
@ -181,8 +180,6 @@ public class EntityMetamodel implements Serializable {
boolean foundCollection = false; boolean foundCollection = false;
boolean foundMutable = false; boolean foundMutable = false;
boolean foundNonIdentifierPropertyNamedId = false; boolean foundNonIdentifierPropertyNamedId = false;
boolean foundInsertGeneratedValue = false;
boolean foundUpdateGeneratedValue = false;
boolean foundUpdateableNaturalIdProperty = false; boolean foundUpdateableNaturalIdProperty = false;
while ( iter.hasNext() ) { while ( iter.hasNext() ) {
@ -379,7 +376,7 @@ public class EntityMetamodel implements Serializable {
} }
entityMode = persistentClass.hasPojoRepresentation() ? EntityMode.POJO : EntityMode.MAP; 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 ); final String tuplizerClassName = persistentClass.getTuplizerImplClassName( entityMode );
if ( tuplizerClassName == null ) { if ( tuplizerClassName == null ) {
entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, persistentClass ); entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, persistentClass );
@ -514,10 +511,6 @@ public class EntityMetamodel implements Serializable {
public ValueGenerationStrategyException(String message) { public ValueGenerationStrategyException(String message) {
super( message ); super( message );
} }
public ValueGenerationStrategyException(String message, Throwable cause) {
super( message, cause );
}
} }
private static class CompositeGenerationStrategyPairBuilder { private static class CompositeGenerationStrategyPairBuilder {
@ -540,7 +533,7 @@ public class EntityMetamodel implements Serializable {
private void add(InMemoryValueGenerationStrategy inMemoryStrategy) { private void add(InMemoryValueGenerationStrategy inMemoryStrategy) {
if ( inMemoryStrategies == null ) { if ( inMemoryStrategies == null ) {
inMemoryStrategies = new ArrayList<InMemoryValueGenerationStrategy>(); inMemoryStrategies = new ArrayList<>();
} }
inMemoryStrategies.add( inMemoryStrategy ); inMemoryStrategies.add( inMemoryStrategy );
@ -551,7 +544,7 @@ public class EntityMetamodel implements Serializable {
private void add(InDatabaseValueGenerationStrategy inDatabaseStrategy) { private void add(InDatabaseValueGenerationStrategy inDatabaseStrategy) {
if ( inDatabaseStrategies == null ) { if ( inDatabaseStrategies == null ) {
inDatabaseStrategies = new ArrayList<InDatabaseValueGenerationStrategy>(); inDatabaseStrategies = new ArrayList<>();
} }
inDatabaseStrategies.add( inDatabaseStrategy ); 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) { private void mapPropertyToIndex(Property prop, int i) {
propertyIndexes.put( prop.getName(), i ); propertyIndexes.put( prop.getName(), i );