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[] propertySelectable;
private final List<Integer> lobProperties = new ArrayList<Integer>();
private final List<Integer> 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<String> affectingFetchProfileNames = new HashSet<String>();
private final Set<String> 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 );
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] );
// todo : probably best to add to dirtyFields if not-null
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.<String>emptySet()
Collections.emptySet()
).toFromFragmentString();
}
@ -3699,7 +3719,7 @@ public abstract class AbstractEntityPersister
alias,
innerJoin,
includeSubclasses,
Collections.<String>emptySet()
Collections.emptySet()
).toWhereFragmentString();
}
@ -5380,7 +5400,6 @@ public abstract class AbstractEntityPersister
// EntityDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private EntityIdentifierDefinition entityIdentifierDefinition;
private Iterable<AttributeDefinition> embeddedCompositeIdentifierAttributes;
private Iterable<AttributeDefinition> attributeDefinitions;
@Override
@ -5405,8 +5424,7 @@ public abstract class AbstractEntityPersister
}
public String[][] getPolymorphicJoinColumns(String lhsTableAlias, String propertyPath) {
Set<String> subclassEntityNames = (Set<String>) getEntityMetamodel()
.getSubclassEntityNames();
Set<String> subclassEntityNames = getEntityMetamodel().getSubclassEntityNames();
// We will collect all the join columns from the LHS subtypes here
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
// 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() );
@ -5542,7 +5560,7 @@ public abstract class AbstractEntityPersister
// }
this.attributeDefinitions = Collections.unmodifiableList(
new ArrayList<AttributeDefinition>( 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)

View File

@ -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<String, Integer> propertyIndexes = new HashMap<String, Integer>();
private final Map<String, Integer> 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<Integer> naturalIdNumbers = new ArrayList<Integer>();
List<Integer> 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<InMemoryValueGenerationStrategy>();
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<InDatabaseValueGenerationStrategy>();
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 );