HHH-7322 : Integrate one-to-many cascade and fetch mode to persisters

This commit is contained in:
Gail Badner 2012-06-06 12:42:55 -07:00
parent 92c7b2d04f
commit 503949b563
2 changed files with 153 additions and 99 deletions

View File

@ -99,6 +99,10 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.Fetchable;
import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding; import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
@ -160,7 +164,7 @@ public abstract class AbstractEntityPersister
private final boolean hasSubselectLoadableCollections; private final boolean hasSubselectLoadableCollections;
protected final String rowIdName; protected final String rowIdName;
private final Set lazyProperties; private final Set<String> lazyProperties;
// The optional SQL string defined in the where attribute // The optional SQL string defined in the where attribute
private final String sqlWhereString; private final String sqlWhereString;
@ -566,13 +570,13 @@ public abstract class AbstractEntityPersister
propertySelectable = new boolean[hydrateSpan]; propertySelectable = new boolean[hydrateSpan];
propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnUpdateable = new boolean[hydrateSpan][];
propertyColumnInsertable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][];
HashSet thisClassProperties = new HashSet(); Set<Property> thisClassProperties = new HashSet<Property>();
lazyProperties = new HashSet(); lazyProperties = new HashSet<String>();
ArrayList lazyNames = new ArrayList(); List<String> lazyNames = new ArrayList<String>();
ArrayList lazyNumbers = new ArrayList(); List<Integer> lazyNumbers = new ArrayList<Integer>();
ArrayList lazyTypes = new ArrayList(); List<Type> lazyTypes = new ArrayList<Type>();
ArrayList lazyColAliases = new ArrayList(); List<String[]> lazyColAliases = new ArrayList<String[]>();
iter = persistentClass.getPropertyClosureIterator(); iter = persistentClass.getPropertyClosureIterator();
i = 0; i = 0;
@ -865,13 +869,14 @@ public abstract class AbstractEntityPersister
propertySelectable = new boolean[hydrateSpan]; propertySelectable = new boolean[hydrateSpan];
propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnUpdateable = new boolean[hydrateSpan][];
propertyColumnInsertable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][];
HashSet thisClassProperties = new HashSet(); Set<AttributeBinding> thisClassProperties = new HashSet<AttributeBinding>();
lazyProperties = new HashSet<String>();
List<String> lazyNames = new ArrayList<String>();
List<Integer> lazyNumbers = new ArrayList<Integer>();
List<Type> lazyTypes = new ArrayList<Type>();
List<String[]> lazyColAliases = new ArrayList<String[]>();
lazyProperties = new HashSet();
ArrayList lazyNames = new ArrayList();
ArrayList lazyNumbers = new ArrayList();
ArrayList lazyTypes = new ArrayList();
ArrayList lazyColAliases = new ArrayList();
i = 0; i = 0;
boolean foundFormula = false; boolean foundFormula = false;
@ -940,10 +945,7 @@ public abstract class AbstractEntityPersister
lazyColAliases.add( colAliases ); lazyColAliases.add( colAliases );
} }
propertySelectable[i] = !attributeBinding.isBackRef();
// TODO: fix this when backrefs are working
//propertySelectable[i] = singularAttributeBinding.isBackRef();
propertySelectable[i] = true;
propertyUniqueness[i] = attributeBinding.isAlternateUniqueKey(); propertyUniqueness[i] = attributeBinding.isAlternateUniqueKey();
@ -987,21 +989,25 @@ public abstract class AbstractEntityPersister
continue; continue;
} }
if ( ! attributeBinding.getAttribute().isSingular() ) { names.add( attributeBinding.getAttribute().getName() );
// collections handled separately classes.add( ( (EntityBinding) attributeBinding.getContainer() ).getEntity().getName() );
continue; boolean isDefinedBySubclass = ! thisClassProperties.contains( attributeBinding );
}
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
names.add( singularAttributeBinding.getAttribute().getName() );
classes.add( ( (EntityBinding) singularAttributeBinding.getContainer() ).getEntity().getName() );
boolean isDefinedBySubclass = ! thisClassProperties.contains( singularAttributeBinding );
definedBySubclass.add( isDefinedBySubclass ); definedBySubclass.add( isDefinedBySubclass );
propNullables.add( singularAttributeBinding.isNullable() || isDefinedBySubclass ); //TODO: is this completely correct? // TODOFix this when join tables are supported...
types.add( singularAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); //propNullables.add( attributeBinding.isOptional() || isDefinedBySubclass );
propNullables.add(
! attributeBinding.getAttribute().isSingular() ||
( (SingularAttributeBinding) attributeBinding).isNullable() ||
isDefinedBySubclass
);
types.add( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() );
final int span = singularAttributeBinding.getRelationalValueBindings().size();
List<RelationalValueBinding> relationalValueBindings =
attributeBinding.getAttribute().isSingular() ?
( (SingularAttributeBinding) attributeBinding ).getRelationalValueBindings() :
null;
final int span = relationalValueBindings == null ? 0 : relationalValueBindings.size();
String[] cols = new String[ span ]; String[] cols = new String[ span ];
String[] readers = new String[ span ]; String[] readers = new String[ span ];
String[] readerTemplates = new String[ span ]; String[] readerTemplates = new String[ span ];
@ -1009,8 +1015,10 @@ public abstract class AbstractEntityPersister
int[] colnos = new int[ span ]; int[] colnos = new int[ span ];
int[] formnos = new int[ span ]; int[] formnos = new int[ span ];
int l = 0; int l = 0;
Boolean lazy = singularAttributeBinding.isLazy() && lazyAvailable; Boolean lazy = attributeBinding.isLazy() && lazyAvailable;
for ( RelationalValueBinding valueBinding : singularAttributeBinding.getRelationalValueBindings() ) {
if ( relationalValueBindings != null ) {
for ( RelationalValueBinding valueBinding : relationalValueBindings ) {
if ( valueBinding.isDerived() ) { if ( valueBinding.isDerived() ) {
DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getValue() ); DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getValue() );
String template = getTemplateFromString( derivedValue.getExpression(), factory ); String template = getTemplateFromString( derivedValue.getExpression(), factory );
@ -1036,8 +1044,7 @@ public abstract class AbstractEntityPersister
) )
); );
columnsLazy.add( lazy ); columnsLazy.add( lazy );
// TODO: properties only selectable if they are non-plural??? columnSelectables.add( ! attributeBinding.isBackRef() );
columnSelectables.add( singularAttributeBinding.getAttribute().isSingular() );
readers[l] = readers[l] =
col.getReadFragment() == null ? col.getReadFragment() == null ?
@ -1049,6 +1056,7 @@ public abstract class AbstractEntityPersister
} }
l++; l++;
} }
}
propColumns.add( cols ); propColumns.add( cols );
propColumnReaders.add( readers ); propColumnReaders.add( readers );
propColumnReaderTemplates.add( readerTemplates ); propColumnReaderTemplates.add( readerTemplates );
@ -1056,14 +1064,26 @@ public abstract class AbstractEntityPersister
propColumnNumbers.add( colnos ); propColumnNumbers.add( colnos );
propFormulaNumbers.add( formnos ); propFormulaNumbers.add( formnos );
if ( singularAttributeBinding.isAssociation() ) { CascadeStyle cascadeStyle = null;
SingularAssociationAttributeBinding associationAttributeBinding = if ( attributeBinding.isAssociation() ) {
(SingularAssociationAttributeBinding) singularAttributeBinding; if ( attributeBinding.getAttribute().isSingular() ) {
cascades.add( associationAttributeBinding.getCascadeStyle() ); cascadeStyle = ( ( SingularAssociationAttributeBinding) attributeBinding ).getCascadeStyle();
joinedFetchesList.add( associationAttributeBinding.getFetchMode() ); }
else {
PluralAttributeElementBinding pluralAttributeElementBinding =
( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding();
cascadeStyle = ( (PluralAttributeAssociationElementBinding) pluralAttributeElementBinding).getCascadeStyle();
}
}
if ( cascadeStyle == null ) {
cascadeStyle = CascadeStyle.NONE;
}
cascades.add( cascadeStyle );
if ( attributeBinding instanceof Fetchable ) {
joinedFetchesList.add( ( (Fetchable) attributeBinding ).getFetchMode() );
} }
else { else {
cascades.add( CascadeStyle.NONE );
joinedFetchesList.add( FetchMode.SELECT ); joinedFetchesList.add( FetchMode.SELECT );
} }
} }
@ -1204,7 +1224,9 @@ public abstract class AbstractEntityPersister
final Serializable id, final Serializable id,
final EntityEntry entry) { final EntityEntry entry) {
if ( !hasLazyProperties() ) throw new AssertionFailure( "no lazy properties" ); if ( !hasLazyProperties() ) {
throw new AssertionFailure( "no lazy properties" );
}
LOG.trace( "Initializing lazy properties from datastore" ); LOG.trace( "Initializing lazy properties from datastore" );
@ -1673,9 +1695,13 @@ public abstract class AbstractEntityPersister
} }
Object nextVersion = getVersionType().next( currentVersion, session ); Object nextVersion = getVersionType().next( currentVersion, session );
if (LOG.isTraceEnabled()) LOG.trace("Forcing version increment [" + MessageHelper.infoString(this, id, getFactory()) + "; " if ( LOG.isTraceEnabled() ) {
LOG.trace(
"Forcing version increment [" + MessageHelper.infoString( this, id, getFactory() ) + "; "
+ getVersionType().toLoggableString( currentVersion, getFactory() ) + " -> " + getVersionType().toLoggableString( currentVersion, getFactory() ) + " -> "
+ getVersionType().toLoggableString(nextVersion, getFactory()) + "]"); + getVersionType().toLoggableString( nextVersion, getFactory() ) + "]"
);
}
// todo : cache this sql... // todo : cache this sql...
String versionIncrementString = generateVersionIncrementUpdateString(); String versionIncrementString = generateVersionIncrementUpdateString();
@ -2866,9 +2892,10 @@ public abstract class AbstractEntityPersister
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Inserting entity: {0}", MessageHelper.infoString( this, id, getFactory() ) ); LOG.tracev( "Inserting entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
if ( j == 0 && isVersioned() ) if ( j == 0 && isVersioned() ) {
LOG.tracev( "Version: {0}", Versioning.getVersion( fields, this ) ); LOG.tracev( "Version: {0}", Versioning.getVersion( fields, this ) );
} }
}
// TODO : shouldn't inserts be Expectations.NONE? // TODO : shouldn't inserts be Expectations.NONE?
final Expectation expectation = Expectations.appropriateExpectation( insertResultCheckStyles[j] ); final Expectation expectation = Expectations.appropriateExpectation( insertResultCheckStyles[j] );
@ -3009,9 +3036,10 @@ public abstract class AbstractEntityPersister
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Updating entity: {0}", MessageHelper.infoString( this, id, getFactory() ) ); LOG.tracev( "Updating entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
if ( useVersion ) if ( useVersion ) {
LOG.tracev( "Existing version: {0} -> New version:{1}", oldVersion, fields[getVersionProperty()] ); LOG.tracev( "Existing version: {0} -> New version:{1}", oldVersion, fields[getVersionProperty()] );
} }
}
try { try {
int index = 1; // starting index int index = 1; // starting index
@ -3127,9 +3155,10 @@ public abstract class AbstractEntityPersister
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Deleting entity: {0}", MessageHelper.infoString( this, id, getFactory() ) ); LOG.tracev( "Deleting entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
if ( useVersion ) if ( useVersion ) {
LOG.tracev( "Version: {0}", version ); LOG.tracev( "Version: {0}", version );
} }
}
if ( isTableCascadeDeleteEnabled( j ) ) { if ( isTableCascadeDeleteEnabled( j ) ) {
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
@ -3434,24 +3463,50 @@ public abstract class AbstractEntityPersister
protected void logStaticSQL() { protected void logStaticSQL() {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debugf("Static SQL for entity: %s", getEntityName()); LOG.debugf("Static SQL for entity: %s", getEntityName());
if (sqlLazySelectString != null) LOG.debugf(" Lazy select: %s", sqlLazySelectString); if ( sqlLazySelectString != null ) {
if (sqlVersionSelectString != null) LOG.debugf(" Version select: %s", sqlVersionSelectString); LOG.debugf( " Lazy select: %s", sqlLazySelectString );
if (sqlSnapshotSelectString != null) LOG.debugf(" Snapshot select: %s", sqlSnapshotSelectString); }
if ( sqlVersionSelectString != null ) {
LOG.debugf( " Version select: %s", sqlVersionSelectString );
}
if ( sqlSnapshotSelectString != null ) {
LOG.debugf( " Snapshot select: %s", sqlSnapshotSelectString );
}
for ( int j = 0; j < getTableSpan(); j++ ) { for ( int j = 0; j < getTableSpan(); j++ ) {
LOG.debugf(" Insert %s: %s", j, getSQLInsertStrings()[j]); LOG.debugf(" Insert %s: %s", j, getSQLInsertStrings()[j]);
LOG.debugf(" Update %s: %s", j, getSQLUpdateStrings()[j]); LOG.debugf(" Update %s: %s", j, getSQLUpdateStrings()[j]);
LOG.debugf(" Delete %s: %s", j, getSQLDeleteStrings()[j]); LOG.debugf(" Delete %s: %s", j, getSQLDeleteStrings()[j]);
} }
if (sqlIdentityInsertString != null) LOG.debugf(" Identity insert: %s", sqlIdentityInsertString); if ( sqlIdentityInsertString != null ) {
if (sqlUpdateByRowIdString != null) LOG.debugf(" Update by row id (all fields): %s", sqlUpdateByRowIdString); LOG.debugf( " Identity insert: %s", sqlIdentityInsertString );
if (sqlLazyUpdateByRowIdString != null) LOG.debugf(" Update by row id (non-lazy fields): %s", }
sqlLazyUpdateByRowIdString); if ( sqlUpdateByRowIdString != null ) {
if (sqlInsertGeneratedValuesSelectString != null) LOG.debugf("Insert-generated property select: %s", LOG.debugf( " Update by row id (all fields): %s", sqlUpdateByRowIdString );
sqlInsertGeneratedValuesSelectString); }
if (sqlUpdateGeneratedValuesSelectString != null) LOG.debugf("Update-generated property select: %s", if ( sqlLazyUpdateByRowIdString != null ) {
sqlUpdateGeneratedValuesSelectString); LOG.debugf(
if (sqlEntityIdByNaturalIdString != null) LOG.debugf("Id by Natural Id: %s", " Update by row id (non-lazy fields): %s",
sqlEntityIdByNaturalIdString); sqlLazyUpdateByRowIdString
);
}
if ( sqlInsertGeneratedValuesSelectString != null ) {
LOG.debugf(
"Insert-generated property select: %s",
sqlInsertGeneratedValuesSelectString
);
}
if ( sqlUpdateGeneratedValuesSelectString != null ) {
LOG.debugf(
"Update-generated property select: %s",
sqlUpdateGeneratedValuesSelectString
);
}
if ( sqlEntityIdByNaturalIdString != null ) {
LOG.debugf(
"Id by Natural Id: %s",
sqlEntityIdByNaturalIdString
);
}
} }
} }

View File

@ -129,13 +129,12 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
} }
private PropertyAccessor buildPropertyAccessor(AttributeBinding mappedProperty) { private PropertyAccessor buildPropertyAccessor(AttributeBinding mappedProperty) {
// TODO: fix when backrefs are working in new metamodel if ( mappedProperty.isBackRef() ) {
//if ( mappedProperty.isBackRef() ) { return PropertyAccessorFactory.getPropertyAccessor( null, mappedProperty.getPropertyAccessorName() );
// return mappedProperty.getPropertyAccessor( null ); }
//} else {
//else {
return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); return PropertyAccessorFactory.getDynamicMapPropertyAccessor();
//} }
} }
/** /**