HHH-14329 consider mutable types always as potentially dirty when using DirtinessTracker
This commit is contained in:
parent
b15974732b
commit
e891a0296c
|
@ -411,7 +411,7 @@ public class EnhancerImpl implements Enhancer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( enhancementContext, ctField );
|
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( enhancementContext, ctField );
|
||||||
if ( enhancementContext.isPersistentField( annotatedField ) && !enhancementContext.isMappedCollection( annotatedField ) ) {
|
if ( enhancementContext.isPersistentField( annotatedField ) && enhancementContext.isMappedCollection( annotatedField ) ) {
|
||||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||||
collectionList.add( annotatedField );
|
collectionList.add( annotatedField );
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ public class EnhancerImpl implements Enhancer {
|
||||||
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
|
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
|
||||||
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
|
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
|
||||||
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( enhancementContext, ctField );
|
AnnotatedFieldDescription annotatedField = new AnnotatedFieldDescription( enhancementContext, ctField );
|
||||||
if ( enhancementContext.isPersistentField( annotatedField ) && !enhancementContext.isMappedCollection( annotatedField ) ) {
|
if ( enhancementContext.isPersistentField( annotatedField ) && enhancementContext.isMappedCollection( annotatedField ) ) {
|
||||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||||
collectionList.add( annotatedField );
|
collectionList.add( annotatedField );
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,7 +283,7 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
|
||||||
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
|
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
|
if ( enhancementContext.isPersistentField( ctField ) && enhancementContext.isMappedCollection( ctField ) ) {
|
||||||
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
|
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
|
||||||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
|
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
|
||||||
collectionList.add( ctField );
|
collectionList.add( ctField );
|
||||||
|
@ -314,7 +314,7 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
|
||||||
|
|
||||||
for ( CtField ctField : managedCtSuperclass.getDeclaredFields() ) {
|
for ( CtField ctField : managedCtSuperclass.getDeclaredFields() ) {
|
||||||
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
|
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
|
||||||
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
|
if ( enhancementContext.isPersistentField( ctField ) && enhancementContext.isMappedCollection( ctField ) ) {
|
||||||
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
|
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
|
||||||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
|
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
|
||||||
collectionList.add( ctField );
|
collectionList.add( ctField );
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.bytecode.enhance.spi;
|
package org.hibernate.bytecode.enhance.spi;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Convert;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
@ -106,7 +108,13 @@ public class DefaultEnhancementContext implements EnhancementContext {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isMappedCollection(UnloadedField field) {
|
public boolean isMappedCollection(UnloadedField field) {
|
||||||
return field.hasAnnotation( OneToMany.class ) || field.hasAnnotation( ManyToMany.class ) || field.hasAnnotation( ElementCollection.class );
|
// If the collection is definitely a plural attribute, we respect that
|
||||||
|
if (field.hasAnnotation( OneToMany.class ) || field.hasAnnotation( ManyToMany.class ) || field.hasAnnotation( ElementCollection.class )) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// But a collection might be treated like a singular attribute if it is annotated with `@Basic`
|
||||||
|
// If no annotations are given though, a collection is treated like a OneToMany
|
||||||
|
return !field.hasAnnotation( Basic.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.engine.spi.Status;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.UniqueKeyLoadable;
|
import org.hibernate.persister.entity.UniqueKeyLoadable;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base implementation of EntityEntry
|
* A base implementation of EntityEntry
|
||||||
|
@ -346,7 +347,24 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
|
||||||
@SuppressWarnings( {"SimplifiableIfStatement"})
|
@SuppressWarnings( {"SimplifiableIfStatement"})
|
||||||
private boolean isUnequivocallyNonDirty(Object entity) {
|
private boolean isUnequivocallyNonDirty(Object entity) {
|
||||||
if ( entity instanceof SelfDirtinessTracker ) {
|
if ( entity instanceof SelfDirtinessTracker ) {
|
||||||
return ! persister.hasCollections() && ! ( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
|
boolean uninitializedProxy = false;
|
||||||
|
if ( entity instanceof PersistentAttributeInterceptable ) {
|
||||||
|
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) entity;
|
||||||
|
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
|
||||||
|
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
|
||||||
|
EnhancementAsProxyLazinessInterceptor enhancementAsProxyLazinessInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
|
||||||
|
// When a proxy has dirty attributes, we have to treat it like a normal entity to flush changes
|
||||||
|
uninitializedProxy = !enhancementAsProxyLazinessInterceptor.isInitialized() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( entity instanceof HibernateProxy ) {
|
||||||
|
uninitializedProxy = ( (HibernateProxy) entity ).getHibernateLazyInitializer()
|
||||||
|
.isUninitialized();
|
||||||
|
}
|
||||||
|
// we never have to check an uninitialized proxy
|
||||||
|
return uninitializedProxy || !persister.hasCollections()
|
||||||
|
&& !persister.hasMutableProperties()
|
||||||
|
&& !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( entity instanceof PersistentAttributeInterceptable ) {
|
if ( entity instanceof PersistentAttributeInterceptable ) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.engine.internal.Nullability;
|
||||||
import org.hibernate.engine.internal.Versioning;
|
import org.hibernate.engine.internal.Versioning;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
|
import org.hibernate.engine.spi.ManagedEntity;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||||
|
@ -39,6 +40,7 @@ import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
|
||||||
import org.hibernate.metadata.ClassMetadata;
|
import org.hibernate.metadata.ClassMetadata;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
@ -525,18 +527,13 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
|
||||||
|
|
||||||
if ( dirtyProperties == null ) {
|
if ( dirtyProperties == null ) {
|
||||||
if ( entity instanceof SelfDirtinessTracker ) {
|
if ( entity instanceof SelfDirtinessTracker ) {
|
||||||
if ( ( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes() ) {
|
if ( ( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes() || persister.hasMutableProperties() ) {
|
||||||
int[] dirty = persister.resolveAttributeIndexes( ( (SelfDirtinessTracker) entity ).$$_hibernate_getDirtyAttributes() );
|
dirtyProperties = persister.resolveDirtyAttributeIndexes(
|
||||||
|
values,
|
||||||
// HHH-12051 - filter non-updatable attributes
|
loadedState,
|
||||||
// TODO: add Updatability to EnhancementContext and skip dirty tracking of those attributes
|
( (SelfDirtinessTracker) entity ).$$_hibernate_getDirtyAttributes(),
|
||||||
int count = 0;
|
session
|
||||||
for ( int i : dirty ) {
|
);
|
||||||
if ( persister.getPropertyUpdateability()[i] ) {
|
|
||||||
dirty[count++] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dirtyProperties = count == 0 ? ArrayHelper.EMPTY_INT_ARRAY : count == dirty.length ? dirty : Arrays.copyOf( dirty, count );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dirtyProperties = ArrayHelper.EMPTY_INT_ARRAY;
|
dirtyProperties = ArrayHelper.EMPTY_INT_ARRAY;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -67,7 +68,6 @@ import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.CascadingAction;
|
|
||||||
import org.hibernate.engine.spi.CascadingActions;
|
import org.hibernate.engine.spi.CascadingActions;
|
||||||
import org.hibernate.engine.spi.CollectionKey;
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
|
@ -81,6 +81,7 @@ import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.ValueInclusion;
|
import org.hibernate.engine.spi.ValueInclusion;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
|
@ -104,7 +105,6 @@ import org.hibernate.loader.custom.sql.SQLQueryParser;
|
||||||
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
||||||
import org.hibernate.loader.entity.CacheEntityLoaderHelper;
|
import org.hibernate.loader.entity.CacheEntityLoaderHelper;
|
||||||
import org.hibernate.loader.entity.CascadeEntityLoader;
|
import org.hibernate.loader.entity.CascadeEntityLoader;
|
||||||
import org.hibernate.loader.entity.plan.DynamicBatchingEntityLoaderBuilder;
|
|
||||||
import org.hibernate.loader.entity.EntityLoader;
|
import org.hibernate.loader.entity.EntityLoader;
|
||||||
import org.hibernate.loader.entity.UniqueEntityLoader;
|
import org.hibernate.loader.entity.UniqueEntityLoader;
|
||||||
import org.hibernate.loader.entity.plan.MultiEntityLoadingSupport;
|
import org.hibernate.loader.entity.plan.MultiEntityLoadingSupport;
|
||||||
|
@ -2261,6 +2261,52 @@ public abstract class AbstractEntityPersister
|
||||||
return Arrays.copyOf( fields, counter );
|
return Arrays.copyOf( fields, counter );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] resolveDirtyAttributeIndexes(
|
||||||
|
final Object[] currentState,
|
||||||
|
final Object[] previousState,
|
||||||
|
final String[] attributeNames,
|
||||||
|
final SessionImplementor session) {
|
||||||
|
final BitSet mutablePropertiesIndexes = entityMetamodel.getMutablePropertiesIndexes();
|
||||||
|
final int estimatedSize = attributeNames == null ? 0 : attributeNames.length + mutablePropertiesIndexes.cardinality();
|
||||||
|
final List<Integer> fields = new ArrayList<>( estimatedSize );
|
||||||
|
if ( estimatedSize == 0 ) {
|
||||||
|
return ArrayHelper.EMPTY_INT_ARRAY;
|
||||||
|
}
|
||||||
|
if ( !mutablePropertiesIndexes.isEmpty() ) {
|
||||||
|
// We have to check the state for "mutable" properties as dirty tracking isn't aware of mutable types
|
||||||
|
final Type[] propertyTypes = entityMetamodel.getPropertyTypes();
|
||||||
|
final boolean[] propertyCheckability = entityMetamodel.getPropertyCheckability();
|
||||||
|
mutablePropertiesIndexes.stream().forEach( i -> {
|
||||||
|
// This is kindly borrowed from org.hibernate.type.TypeHelper.findDirty
|
||||||
|
final boolean dirty = currentState[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY &&
|
||||||
|
( previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ||
|
||||||
|
( propertyCheckability[i]
|
||||||
|
&& propertyTypes[i].isDirty(
|
||||||
|
previousState[i],
|
||||||
|
currentState[i],
|
||||||
|
propertyColumnUpdateable[i],
|
||||||
|
session
|
||||||
|
) ) );
|
||||||
|
if ( dirty ) {
|
||||||
|
fields.add( i );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( attributeNames != null ) {
|
||||||
|
final boolean[] propertyUpdateability = entityMetamodel.getPropertyUpdateability();
|
||||||
|
for ( String attributeName : attributeNames ) {
|
||||||
|
final Integer index = entityMetamodel.getPropertyIndexOrNull( attributeName );
|
||||||
|
if ( index != null && propertyUpdateability[index] && !fields.contains( index ) ) {
|
||||||
|
fields.add( index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArrayHelper.toIntArray( fields );
|
||||||
|
}
|
||||||
|
|
||||||
protected String[] getSubclassPropertySubclassNameClosure() {
|
protected String[] getSubclassPropertySubclassNameClosure() {
|
||||||
return subclassPropertySubclassNameClosure;
|
return subclassPropertySubclassNameClosure;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import org.hibernate.LockOptions;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
||||||
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
||||||
import org.hibernate.bytecode.spi.NotInstrumentedException;
|
|
||||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||||
|
@ -25,6 +24,7 @@ import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.EntityEntryFactory;
|
import org.hibernate.engine.spi.EntityEntryFactory;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.ValueInclusion;
|
import org.hibernate.engine.spi.ValueInclusion;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
@ -840,6 +840,25 @@ public interface EntityPersister extends EntityDefinition {
|
||||||
*/
|
*/
|
||||||
int[] resolveAttributeIndexes(String[] attributeNames);
|
int[] resolveAttributeIndexes(String[] attributeNames);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link #resolveAttributeIndexes(String[])} but also always returns mutable attributes
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* @param loadedState
|
||||||
|
* @param attributeNames Array of names to be resolved
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* @return A set of unique indexes of the attribute names found in the metamodel
|
||||||
|
*/
|
||||||
|
default int[] resolveDirtyAttributeIndexes(
|
||||||
|
Object[] values,
|
||||||
|
Object[] loadedState,
|
||||||
|
String[] attributeNames,
|
||||||
|
SessionImplementor session) {
|
||||||
|
return resolveAttributeIndexes( attributeNames );
|
||||||
|
}
|
||||||
|
|
||||||
boolean canUseReferenceCacheEntries();
|
boolean canUseReferenceCacheEntries();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.tuple.entity;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -44,6 +45,7 @@ import org.hibernate.tuple.PropertyFactory;
|
||||||
import org.hibernate.tuple.ValueGeneration;
|
import org.hibernate.tuple.ValueGeneration;
|
||||||
import org.hibernate.tuple.ValueGenerator;
|
import org.hibernate.tuple.ValueGenerator;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
import org.hibernate.type.ComponentType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
@ -97,7 +99,7 @@ public class EntityMetamodel implements Serializable {
|
||||||
|
|
||||||
private final Map<String, Integer> propertyIndexes = new HashMap<>();
|
private final Map<String, Integer> propertyIndexes = new HashMap<>();
|
||||||
private final boolean hasCollections;
|
private final boolean hasCollections;
|
||||||
private final boolean hasMutableProperties;
|
private final BitSet mutablePropertiesIndexes;
|
||||||
private final boolean hasLazyProperties;
|
private final boolean hasLazyProperties;
|
||||||
private final boolean hasNonIdentifierPropertyNamedId;
|
private final boolean hasNonIdentifierPropertyNamedId;
|
||||||
|
|
||||||
|
@ -208,7 +210,7 @@ public class EntityMetamodel implements Serializable {
|
||||||
int tempVersionProperty = NO_VERSION_INDX;
|
int tempVersionProperty = NO_VERSION_INDX;
|
||||||
boolean foundCascade = false;
|
boolean foundCascade = false;
|
||||||
boolean foundCollection = false;
|
boolean foundCollection = false;
|
||||||
boolean foundMutable = false;
|
BitSet mutableIndexes = new BitSet();
|
||||||
boolean foundNonIdentifierPropertyNamedId = false;
|
boolean foundNonIdentifierPropertyNamedId = false;
|
||||||
boolean foundUpdateableNaturalIdProperty = false;
|
boolean foundUpdateableNaturalIdProperty = false;
|
||||||
|
|
||||||
|
@ -318,8 +320,9 @@ public class EntityMetamodel implements Serializable {
|
||||||
foundCollection = true;
|
foundCollection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( propertyTypes[i].isMutable() && propertyCheckability[i] ) {
|
// Component types are dirty tracked as well so they are not exactly mutable for the "maybeDirty" check
|
||||||
foundMutable = true;
|
if ( propertyTypes[i].isMutable() && propertyCheckability[i] && !( propertyTypes[i] instanceof ComponentType ) ) {
|
||||||
|
mutableIndexes.set( i );
|
||||||
}
|
}
|
||||||
|
|
||||||
mapPropertyToIndex(prop, i);
|
mapPropertyToIndex(prop, i);
|
||||||
|
@ -395,7 +398,7 @@ public class EntityMetamodel implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasCollections = foundCollection;
|
hasCollections = foundCollection;
|
||||||
hasMutableProperties = foundMutable;
|
mutablePropertiesIndexes = mutableIndexes;
|
||||||
|
|
||||||
iter = persistentClass.getSubclassIterator();
|
iter = persistentClass.getSubclassIterator();
|
||||||
final Set<String> subclassEntityNamesLocal = new HashSet<>();
|
final Set<String> subclassEntityNamesLocal = new HashSet<>();
|
||||||
|
@ -890,7 +893,11 @@ public class EntityMetamodel implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMutableProperties() {
|
public boolean hasMutableProperties() {
|
||||||
return hasMutableProperties;
|
return !mutablePropertiesIndexes.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitSet getMutablePropertiesIndexes() {
|
||||||
|
return mutablePropertiesIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNonIdentifierPropertyNamedId() {
|
public boolean hasNonIdentifierPropertyNamedId() {
|
||||||
|
|
Loading…
Reference in New Issue