split up TypeHelper
This commit is contained in:
parent
6c3b74d39e
commit
38f4c70e7b
98
hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryHelper.java
vendored
Normal file
98
hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryHelper.java
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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.cache.spi.entry;
|
||||
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Operations for assembly and disassembly of an array of property values.
|
||||
*/
|
||||
class CacheEntryHelper {
|
||||
|
||||
/**
|
||||
* Apply the {@link Type#disassemble} operation across a series of values.
|
||||
*
|
||||
* @param row The values
|
||||
* @param types The value types
|
||||
* @param nonCacheable An array indicating which values to include in the disassembled state
|
||||
* @param session The originating session
|
||||
* @param owner The entity "owning" the values
|
||||
*
|
||||
* @return The disassembled state
|
||||
*/
|
||||
public static Serializable[] disassemble(
|
||||
final Object[] row,
|
||||
final Type[] types,
|
||||
final boolean[] nonCacheable,
|
||||
final SharedSessionContractImplementor session,
|
||||
final Object owner) {
|
||||
Serializable[] disassembled = new Serializable[row.length];
|
||||
for ( int i = 0; i < row.length; i++ ) {
|
||||
if ( nonCacheable!=null && nonCacheable[i] ) {
|
||||
disassembled[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY;
|
||||
}
|
||||
else if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||
| row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
disassembled[i] = (Serializable) row[i];
|
||||
}
|
||||
else {
|
||||
disassembled[i] = types[i].disassemble( row[i], session, owner );
|
||||
}
|
||||
}
|
||||
return disassembled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the {@link Type#assemble} operation across a series of values.
|
||||
*
|
||||
* @param row The values
|
||||
* @param types The value types
|
||||
* @param session The originating session
|
||||
* @param owner The entity "owning" the values
|
||||
* @return The assembled state
|
||||
*/
|
||||
public static Object[] assemble(
|
||||
final Serializable[] row,
|
||||
final Type[] types,
|
||||
final SharedSessionContractImplementor session,
|
||||
final Object owner) {
|
||||
Object[] assembled = new Object[row.length];
|
||||
for ( int i = 0; i < types.length; i++ ) {
|
||||
if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||
|| row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
assembled[i] = row[i];
|
||||
}
|
||||
else {
|
||||
assembled[i] = types[i].assemble( row[i], session, owner );
|
||||
}
|
||||
}
|
||||
return assembled;
|
||||
}
|
||||
|
||||
// public static Object[] assemble(
|
||||
// final Object[] row,
|
||||
// final Type[] types,
|
||||
// final SharedSessionContractImplementor session,
|
||||
// final Object owner) {
|
||||
// Object[] assembled = new Object[row.length];
|
||||
// for ( int i = 0; i < types.length; i++ ) {
|
||||
// if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
// assembled[i] = row[i];
|
||||
// }
|
||||
// else {
|
||||
// assembled[i] = types[i].assemble( (Serializable) row[i], session, owner );
|
||||
// }
|
||||
// }
|
||||
// return assembled;
|
||||
// }
|
||||
|
||||
}
|
|
@ -11,16 +11,12 @@ import java.io.Serializable;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.event.spi.PreLoadEvent;
|
||||
import org.hibernate.event.spi.PreLoadEventListener;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.TypeHelper;
|
||||
|
||||
/**
|
||||
* Standard representation of entity cached data using the "disassembled state".
|
||||
|
@ -51,7 +47,7 @@ public class StandardCacheEntryImpl implements CacheEntry {
|
|||
final SharedSessionContractImplementor session,
|
||||
final Object owner) throws HibernateException {
|
||||
// disassembled state gets put in a new array (we write to cache by value!)
|
||||
this.disassembledState = TypeHelper.disassemble(
|
||||
this.disassembledState = CacheEntryHelper.disassemble(
|
||||
state,
|
||||
persister.getPropertyTypes(),
|
||||
persister.isLazyPropertiesCacheable() ? null : persister.getPropertyLaziness(),
|
||||
|
@ -133,7 +129,7 @@ public class StandardCacheEntryImpl implements CacheEntry {
|
|||
}
|
||||
|
||||
//assembled state gets put in a new array (we read from cache by value!)
|
||||
final Object[] state = TypeHelper.assemble(
|
||||
final Object[] state = CacheEntryHelper.assemble(
|
||||
disassembledState,
|
||||
persister.getPropertyTypes(),
|
||||
session, instance
|
||||
|
|
|
@ -262,7 +262,6 @@ import org.hibernate.type.CollectionType;
|
|||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeHelper;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
|
||||
|
@ -4326,8 +4325,7 @@ public abstract class AbstractEntityPersister
|
|||
return true;
|
||||
}
|
||||
// we still need to verify collection fields to be eagerly loaded by 'join'
|
||||
final NonIdentifierAttribute[] attributes = entityMetamodel.getProperties();
|
||||
for ( NonIdentifierAttribute attribute : attributes ) {
|
||||
for ( NonIdentifierAttribute attribute : entityMetamodel.getProperties() ) {
|
||||
if ( attribute instanceof EntityBasedAssociationAttribute ) {
|
||||
final AssociationType associationType = ( (EntityBasedAssociationAttribute) attribute ).getType();
|
||||
if ( associationType instanceof CollectionType ) {
|
||||
|
@ -4408,7 +4406,7 @@ public abstract class AbstractEntityPersister
|
|||
*/
|
||||
public int[] findDirty(Object[] currentState, Object[] previousState, Object entity, SharedSessionContractImplementor session)
|
||||
throws HibernateException {
|
||||
int[] props = TypeHelper.findDirty(
|
||||
int[] props = DirtyHelper.findDirty(
|
||||
entityMetamodel.getProperties(),
|
||||
currentState,
|
||||
previousState,
|
||||
|
@ -4437,7 +4435,7 @@ public abstract class AbstractEntityPersister
|
|||
*/
|
||||
public int[] findModified(Object[] old, Object[] current, Object entity, SharedSessionContractImplementor session)
|
||||
throws HibernateException {
|
||||
int[] props = TypeHelper.findModified(
|
||||
int[] props = DirtyHelper.findModified(
|
||||
entityMetamodel.getProperties(),
|
||||
current,
|
||||
old,
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.tuple.NonIdentifierAttribute;
|
||||
|
||||
/**
|
||||
* Operations for searching an array of property values for modified elements.
|
||||
*/
|
||||
class DirtyHelper {
|
||||
/**
|
||||
* Determine if any of the given field values are dirty, returning an array containing
|
||||
* indices of the dirty fields.
|
||||
* <p/>
|
||||
* If it is determined that no fields are dirty, null is returned.
|
||||
*
|
||||
* @param properties The property definitions
|
||||
* @param currentState The current state of the entity
|
||||
* @param previousState The baseline state of the entity
|
||||
* @param includeColumns Columns to be included in the dirty checking, per property
|
||||
* @param session The session from which the dirty check request originated.
|
||||
*
|
||||
* @return Array containing indices of the dirty properties, or null if no properties considered dirty.
|
||||
*/
|
||||
public static int[] findDirty(
|
||||
final NonIdentifierAttribute[] properties,
|
||||
final Object[] currentState,
|
||||
final Object[] previousState,
|
||||
final boolean[][] includeColumns,
|
||||
final SharedSessionContractImplementor session) {
|
||||
int[] results = null;
|
||||
int count = 0;
|
||||
int span = properties.length;
|
||||
|
||||
for ( int i = 0; i < span; i++ ) {
|
||||
|
||||
if ( isDirty( properties, currentState, previousState, includeColumns, session, i ) ) {
|
||||
if ( results == null ) {
|
||||
results = new int[span];
|
||||
}
|
||||
results[count++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
return count == 0 ? null : ArrayHelper.trim( results, count );
|
||||
}
|
||||
|
||||
private static boolean isDirty(
|
||||
NonIdentifierAttribute[] properties,
|
||||
Object[] currentState,
|
||||
Object[] previousState,
|
||||
boolean[][] includeColumns,
|
||||
SharedSessionContractImplementor session, int i) {
|
||||
if ( currentState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||
return false;
|
||||
}
|
||||
else if ( previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return properties[i].isDirtyCheckable()
|
||||
&& properties[i].getType().isDirty( previousState[i], currentState[i], includeColumns[i], session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any of the given field values are modified, returning an array containing
|
||||
* indices of the modified fields.
|
||||
* <p/>
|
||||
* If it is determined that no fields are dirty, null is returned.
|
||||
*
|
||||
* @param properties The property definitions
|
||||
* @param currentState The current state of the entity
|
||||
* @param previousState The baseline state of the entity
|
||||
* @param includeColumns Columns to be included in the mod checking, per property
|
||||
* @param includeProperties Array of property indices that identify which properties participate in check
|
||||
* @param session The session from which the dirty check request originated.
|
||||
*
|
||||
* @return Array containing indices of the modified properties, or null if no properties considered modified.
|
||||
**/
|
||||
public static int[] findModified(
|
||||
final NonIdentifierAttribute[] properties,
|
||||
final Object[] currentState,
|
||||
final Object[] previousState,
|
||||
final boolean[][] includeColumns,
|
||||
final boolean[] includeProperties,
|
||||
final SharedSessionContractImplementor session) {
|
||||
int[] results = null;
|
||||
int count = 0;
|
||||
int span = properties.length;
|
||||
|
||||
for ( int i = 0; i < span; i++ ) {
|
||||
if ( isModified( properties, currentState, previousState, includeColumns, includeProperties, session, i ) ) {
|
||||
if ( results == null ) {
|
||||
results = new int[ span ];
|
||||
}
|
||||
results[ count++ ] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( count == 0 ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
int[] trimmed = new int[ count ];
|
||||
System.arraycopy( results, 0, trimmed, 0, count );
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isModified(
|
||||
NonIdentifierAttribute[] properties,
|
||||
Object[] currentState,
|
||||
Object[] previousState,
|
||||
boolean[][] includeColumns,
|
||||
boolean[] includeProperties,
|
||||
SharedSessionContractImplementor session,
|
||||
int i) {
|
||||
return currentState[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||
&& includeProperties[i]
|
||||
&& properties[i].isDirtyCheckable()
|
||||
&& properties[i].getType().isModified( previousState[i], currentState[i], includeColumns[i], session );
|
||||
}
|
||||
}
|
|
@ -136,7 +136,6 @@ import org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl;
|
|||
import org.hibernate.query.sqm.sql.internal.SqmMapEntryResult;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.TypeHelper;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
|
@ -5106,7 +5105,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
final Expression resultExpression = (Expression) whenFragment.getResult().accept( this );
|
||||
inferrableTypeAccessStack.pop();
|
||||
resolved = (MappingModelExpressible<?>) TypeHelper.highestPrecedence( resolved, resultExpression.getExpressionType() );
|
||||
resolved = (MappingModelExpressible<?>) highestPrecedence( resolved, resultExpression.getExpressionType() );
|
||||
|
||||
whenFragments.add(
|
||||
new CaseSimpleExpression.WhenFragment(
|
||||
|
@ -5123,7 +5122,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
otherwise = (Expression) expression.getOtherwise().accept( this );
|
||||
inferrableTypeAccessStack.pop();
|
||||
resolved = (MappingModelExpressible<?>) TypeHelper.highestPrecedence( resolved, otherwise.getExpressionType() );
|
||||
resolved = (MappingModelExpressible<?>) highestPrecedence( resolved, otherwise.getExpressionType() );
|
||||
}
|
||||
|
||||
return new CaseSimpleExpression(
|
||||
|
@ -5151,7 +5150,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
final Expression resultExpression = (Expression) whenFragment.getResult().accept( this );
|
||||
inferrableTypeAccessStack.pop();
|
||||
resolved = (MappingModelExpressible<?>) TypeHelper.highestPrecedence( resolved, resultExpression.getExpressionType() );
|
||||
resolved = (MappingModelExpressible<?>) highestPrecedence( resolved, resultExpression.getExpressionType() );
|
||||
|
||||
whenFragments.add( new CaseSearchedExpression.WhenFragment( whenPredicate, resultExpression ) );
|
||||
}
|
||||
|
@ -5163,7 +5162,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
otherwise = (Expression) expression.getOtherwise().accept( this );
|
||||
inferrableTypeAccessStack.pop();
|
||||
resolved = (MappingModelExpressible<?>) TypeHelper.highestPrecedence( resolved, otherwise.getExpressionType() );
|
||||
resolved = (MappingModelExpressible<?>) highestPrecedence( resolved, otherwise.getExpressionType() );
|
||||
}
|
||||
|
||||
return new CaseSearchedExpression( resolved, whenFragments, otherwise );
|
||||
|
@ -6265,4 +6264,28 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JdbcMappingContainer highestPrecedence(JdbcMappingContainer type1, JdbcMappingContainer type2) {
|
||||
if ( type1 == null ) {
|
||||
return type2;
|
||||
}
|
||||
|
||||
if ( type2 == null ) {
|
||||
return type1;
|
||||
}
|
||||
|
||||
if ( type1 instanceof ModelPart ) {
|
||||
return type1;
|
||||
}
|
||||
|
||||
if ( type2 instanceof ModelPart ) {
|
||||
return type2;
|
||||
}
|
||||
|
||||
// todo (6.0) : we probably want a precedence based on generic resolutions such as those based on Serializable
|
||||
|
||||
// todo (6.0) : anything else to consider?
|
||||
|
||||
return type1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* 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.query.sqm.sql.internal;
|
||||
|
||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TypeHelper {
|
||||
public static JdbcMappingContainer highestPrecedence(JdbcMappingContainer type1, JdbcMappingContainer type2) {
|
||||
if ( type1 == null ) {
|
||||
return type2;
|
||||
}
|
||||
|
||||
if ( type2 == null ) {
|
||||
return type1;
|
||||
}
|
||||
|
||||
if ( type1 instanceof ModelPart ) {
|
||||
return type1;
|
||||
}
|
||||
|
||||
if ( type2 instanceof ModelPart ) {
|
||||
return type2;
|
||||
}
|
||||
|
||||
// todo (6.0) : we probably want a precedence based on generic resolutions such as those based on Serializable
|
||||
|
||||
// todo (6.0) : anything else to consider?
|
||||
|
||||
return type1;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.WrongClassException;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
|
@ -36,9 +37,11 @@ import org.hibernate.loader.entity.CacheEntityLoaderHelper;
|
|||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.UniqueKeyLoadable;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.proxy.map.MapProxy;
|
||||
|
@ -56,7 +59,6 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
|||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeHelper;
|
||||
|
||||
import static org.hibernate.internal.log.LoggingHelper.toLoggableString;
|
||||
|
||||
|
@ -189,6 +191,32 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
);
|
||||
}
|
||||
|
||||
private static void deepCopy(
|
||||
ManagedMappingType containerDescriptor,
|
||||
Object[] source,
|
||||
Object[] target,
|
||||
EntityPersister concreteDescriptor) {
|
||||
containerDescriptor.visitStateArrayContributors(
|
||||
contributor -> {
|
||||
if ( contributor.getAttributeMetadataAccess().resolveAttributeMetadata( concreteDescriptor ).isUpdatable() ) {
|
||||
final int position = contributor.getStateArrayPosition();
|
||||
Object result;
|
||||
if ( source[position] == LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||
|| source[position] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
result = source[position];
|
||||
}
|
||||
else {
|
||||
result = contributor.getAttributeMetadataAccess()
|
||||
.resolveAttributeMetadata(null)
|
||||
.getMutabilityPlan()
|
||||
.deepCopy( source[position] );
|
||||
}
|
||||
target[position] = result;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getInitializedPart() {
|
||||
return referencedModelPart;
|
||||
|
@ -832,11 +860,11 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
else {
|
||||
//take a snapshot
|
||||
TypeHelper.deepCopy(
|
||||
deepCopy(
|
||||
concreteDescriptor,
|
||||
resolvedEntityState,
|
||||
resolvedEntityState,
|
||||
attributeMapping -> attributeMapping.getAttributeMetadataAccess().resolveAttributeMetadata( concreteDescriptor ).isUpdatable()
|
||||
concreteDescriptor
|
||||
);
|
||||
persistenceContext.setEntryStatus( entityEntry, Status.MANAGED );
|
||||
}
|
||||
|
|
|
@ -6,27 +6,19 @@
|
|||
*/
|
||||
package org.hibernate.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.tuple.NonIdentifierAttribute;
|
||||
|
||||
/**
|
||||
* Collection of convenience methods relating to operations across arrays of types...
|
||||
* Certain operations for working with arrays of property values.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated with no real replacement. this was always intended as an internal class
|
||||
*/
|
||||
@Deprecated(since = "6.0")
|
||||
@Internal
|
||||
public class TypeHelper {
|
||||
/**
|
||||
* Disallow instantiation
|
||||
|
@ -34,49 +26,6 @@ public class TypeHelper {
|
|||
private TypeHelper() {
|
||||
}
|
||||
|
||||
public static final BiFunction<StateArrayContributorMapping,Object,Object> DEEP_COPY_VALUE_PRODUCER = (navigable, sourceValue) -> {
|
||||
if ( sourceValue == LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||
|| sourceValue == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
return sourceValue;
|
||||
}
|
||||
else {
|
||||
return navigable.getAttributeMetadataAccess()
|
||||
.resolveAttributeMetadata( null )
|
||||
.getMutabilityPlan()
|
||||
.deepCopy( sourceValue );
|
||||
}
|
||||
};
|
||||
|
||||
public static void deepCopy(
|
||||
ManagedMappingType containerDescriptor,
|
||||
Object[] source,
|
||||
Object[] target,
|
||||
Predicate<StateArrayContributorMapping> copyConditions) {
|
||||
deepCopy(
|
||||
containerDescriptor,
|
||||
source,
|
||||
target,
|
||||
copyConditions,
|
||||
DEEP_COPY_VALUE_PRODUCER
|
||||
);
|
||||
}
|
||||
|
||||
public static void deepCopy(
|
||||
ManagedMappingType containerDescriptor,
|
||||
Object[] source,
|
||||
Object[] target,
|
||||
Predicate<StateArrayContributorMapping> copyConditions,
|
||||
BiFunction<StateArrayContributorMapping, Object, Object> targetValueProducer) {
|
||||
containerDescriptor.visitStateArrayContributors(
|
||||
contributor -> {
|
||||
if ( copyConditions.test( contributor ) ) {
|
||||
final int position = contributor.getStateArrayPosition();
|
||||
target[position] = targetValueProducer.apply( contributor, source[position] );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep copy a series of values from one array to another...
|
||||
*
|
||||
|
@ -106,81 +55,6 @@ public class TypeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the {@link Type#assemble} operation across a series of values.
|
||||
*
|
||||
* @param row The values
|
||||
* @param types The value types
|
||||
* @param session The originating session
|
||||
* @param owner The entity "owning" the values
|
||||
* @return The assembled state
|
||||
*/
|
||||
public static Object[] assemble(
|
||||
final Serializable[] row,
|
||||
final Type[] types,
|
||||
final SharedSessionContractImplementor session,
|
||||
final Object owner) {
|
||||
Object[] assembled = new Object[row.length];
|
||||
for ( int i = 0; i < types.length; i++ ) {
|
||||
if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
assembled[i] = row[i];
|
||||
}
|
||||
else {
|
||||
assembled[i] = types[i].assemble( row[i], session, owner );
|
||||
}
|
||||
}
|
||||
return assembled;
|
||||
}
|
||||
|
||||
public static Object[] assemble(
|
||||
final Object[] row,
|
||||
final Type[] types,
|
||||
final SharedSessionContractImplementor session,
|
||||
final Object owner) {
|
||||
Object[] assembled = new Object[row.length];
|
||||
for ( int i = 0; i < types.length; i++ ) {
|
||||
if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
assembled[i] = row[i];
|
||||
}
|
||||
else {
|
||||
assembled[i] = types[i].assemble( (Serializable) row[i], session, owner );
|
||||
}
|
||||
}
|
||||
return assembled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the {@link Type#disassemble} operation across a series of values.
|
||||
*
|
||||
* @param row The values
|
||||
* @param types The value types
|
||||
* @param nonCacheable An array indicating which values to include in the disassembled state
|
||||
* @param session The originating session
|
||||
* @param owner The entity "owning" the values
|
||||
*
|
||||
* @return The disassembled state
|
||||
*/
|
||||
public static Serializable[] disassemble(
|
||||
final Object[] row,
|
||||
final Type[] types,
|
||||
final boolean[] nonCacheable,
|
||||
final SharedSessionContractImplementor session,
|
||||
final Object owner) {
|
||||
Serializable[] disassembled = new Serializable[row.length];
|
||||
for ( int i = 0; i < row.length; i++ ) {
|
||||
if ( nonCacheable!=null && nonCacheable[i] ) {
|
||||
disassembled[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY;
|
||||
}
|
||||
else if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
disassembled[i] = (Serializable) row[i];
|
||||
}
|
||||
else {
|
||||
disassembled[i] = types[i].disassemble( row[i], session, owner );
|
||||
}
|
||||
}
|
||||
return disassembled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the {@link Type#replace} operation across a series of values.
|
||||
*
|
||||
|
@ -302,109 +176,4 @@ public class TypeHelper {
|
|||
return copied;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any of the given field values are dirty, returning an array containing
|
||||
* indices of the dirty fields.
|
||||
* <p/>
|
||||
* If it is determined that no fields are dirty, null is returned.
|
||||
*
|
||||
* @param properties The property definitions
|
||||
* @param currentState The current state of the entity
|
||||
* @param previousState The baseline state of the entity
|
||||
* @param includeColumns Columns to be included in the dirty checking, per property
|
||||
* @param session The session from which the dirty check request originated.
|
||||
*
|
||||
* @return Array containing indices of the dirty properties, or null if no properties considered dirty.
|
||||
*/
|
||||
public static int[] findDirty(
|
||||
final NonIdentifierAttribute[] properties,
|
||||
final Object[] currentState,
|
||||
final Object[] previousState,
|
||||
final boolean[][] includeColumns,
|
||||
final SharedSessionContractImplementor session) {
|
||||
int[] results = null;
|
||||
int count = 0;
|
||||
int span = properties.length;
|
||||
|
||||
for ( int i = 0; i < span; i++ ) {
|
||||
final boolean dirty;
|
||||
if ( currentState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||
dirty = false;
|
||||
}
|
||||
else if ( previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||
dirty = true;
|
||||
}
|
||||
else if ( properties[i].isDirtyCheckable()
|
||||
&& properties[i].getType().isDirty( previousState[i], currentState[i], includeColumns[i], session ) ) {
|
||||
dirty = true;
|
||||
}
|
||||
else {
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
if ( dirty ) {
|
||||
if ( results == null ) {
|
||||
results = new int[span];
|
||||
}
|
||||
results[count++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( count == 0 ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return ArrayHelper.trim(results, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any of the given field values are modified, returning an array containing
|
||||
* indices of the modified fields.
|
||||
* <p/>
|
||||
* If it is determined that no fields are dirty, null is returned.
|
||||
*
|
||||
* @param properties The property definitions
|
||||
* @param currentState The current state of the entity
|
||||
* @param previousState The baseline state of the entity
|
||||
* @param includeColumns Columns to be included in the mod checking, per property
|
||||
* @param includeProperties Array of property indices that identify which properties participate in check
|
||||
* @param session The session from which the dirty check request originated.
|
||||
*
|
||||
* @return Array containing indices of the modified properties, or null if no properties considered modified.
|
||||
**/
|
||||
public static int[] findModified(
|
||||
final NonIdentifierAttribute[] properties,
|
||||
final Object[] currentState,
|
||||
final Object[] previousState,
|
||||
final boolean[][] includeColumns,
|
||||
final boolean[] includeProperties,
|
||||
final SharedSessionContractImplementor session) {
|
||||
int[] results = null;
|
||||
int count = 0;
|
||||
int span = properties.length;
|
||||
|
||||
for ( int i = 0; i < span; i++ ) {
|
||||
final boolean modified = currentState[ i ] != LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||
&& includeProperties[ i ]
|
||||
&& properties[ i ].isDirtyCheckable()
|
||||
&& properties[ i ].getType().isModified( previousState[ i ], currentState[ i ], includeColumns[ i ], session );
|
||||
if ( modified ) {
|
||||
if ( results == null ) {
|
||||
results = new int[ span ];
|
||||
}
|
||||
results[ count++ ] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( count == 0 ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
int[] trimmed = new int[ count ];
|
||||
System.arraycopy( results, 0, trimmed, 0, count );
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue