HHH-7322 : Integrate one-to-many cascade and fetch mode to persisters
This commit is contained in:
parent
92c7b2d04f
commit
503949b563
|
@ -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() ) {
|
||||||
+ getVersionType().toLoggableString(currentVersion, getFactory()) + " -> "
|
LOG.trace(
|
||||||
+ getVersionType().toLoggableString(nextVersion, getFactory()) + "]");
|
"Forcing version increment [" + MessageHelper.infoString( this, id, getFactory() ) + "; "
|
||||||
|
+ getVersionType().toLoggableString( currentVersion, 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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue