/// <summary> /// Constructs StandardProperty instances. /// </summary> /// <param name="name">The name by which the property can be referenced within /// its owner.</param> /// <param name="node">The node name to use for XML-based representation of this /// property.</param> /// <param name="type">The Hibernate Type of this property.</param> /// <param name="lazy">Should this property be handled lazily?</param> /// <param name="insertable">Is this property an insertable value?</param> /// <param name="updateable">Is this property an updateable value?</param> /// <param name="insertGenerated">Is this property generated in the database on insert?</param> /// <param name="updateGenerated">Is this property generated in the database on update?</param> /// <param name="nullable">Is this property a nullable value?</param> /// <param name="checkable">Is this property a checkable value?</param> /// <param name="versionable">Is this property a versionable value?</param> /// <param name="cascadeStyle">The cascade style for this property's value.</param> public StandardProperty( String name, String node, IType type, bool lazy, bool insertable, bool updateable, bool insertGenerated, bool updateGenerated, bool nullable, bool checkable, bool versionable, Cascades.CascadeStyle cascadeStyle) : base(name, node, type) { this.lazy = lazy; this.insertable = insertable; this.updateable = updateable; this.insertGenerated = insertGenerated; this.updateGenerated = updateGenerated; this.nullable = nullable; this.dirtyCheckable = checkable; this.versionable = versionable; this.cascadeStyle = cascadeStyle; }
/// <summary> /// Disable outer join fetching if this loader obtains an /// upgrade lock mode /// </summary> protected override bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config, Cascades.CascadeStyle cascadeStyle) { return lockMode.GreaterThan(LockMode.Read) ? false : base.IsJoinedFetchEnabled(type, config, cascadeStyle); }
public CascadeEntityJoinWalker(IOuterJoinLoadable persister, Cascades.CascadingAction action, ISessionFactoryImplementor factory) : base(persister, factory, CollectionHelper.EmptyMap) { this.cascadeAction = action; SqlStringBuilder whereCondition = WhereString(Alias, persister.IdentifierColumnNames, persister.IdentifierType, 1) //include the discriminator and class-level where, but not filters .Add(persister.FilterFragment(Alias, CollectionHelper.EmptyMap)); InitAll(whereCondition.ToSqlString(), "", LockMode.Read); }
public DynamicComponentType( string[ ] propertyNames, IType[ ] propertyTypes, OuterJoinFetchStrategy[ ] joinedFetch, Cascades.CascadeStyle[ ] cascade ) { this.propertyNames = propertyNames; this.propertyTypes = propertyTypes; this.joinedFetch = joinedFetch; this.cascade = cascade; propertySpan = propertyTypes.Length; }
protected override JoinType GetJoinType( IAssociationType type, FetchMode config, string path, string lhsTable, string[] lhsColumns, bool nullable, int currentDepth, Cascades.CascadeStyle cascadeStyle) { if (translator.IsJoin(path)) { return translator.GetJoinType(path); } else { if (translator.HasProjection) { return JoinType.None; } else { FetchMode fetchMode = translator.RootCriteria .GetFetchMode(path); if (IsDefaultFetchMode(fetchMode)) { return base.GetJoinType( type, config, path, lhsTable, lhsColumns, nullable, currentDepth, cascadeStyle ); } else { if (fetchMode == FetchMode.Join) { IsDuplicateAssociation(lhsTable, lhsColumns, type); //deliberately ignore return value! return GetJoinType(nullable, currentDepth); } else { return JoinType.None; } } } } }
/// <summary> /// Construct a virtual IdentifierProperty. /// </summary> /// <param name="type">The Hibernate Type for the identifier property.</param> /// <param name="embedded">Is this an embedded identifier.</param> /// <param name="unsavedValue">The value which, if found as the value on the identifier /// property, represents new (i.e., un-saved) instances of the owning entity.</param> /// <param name="identifierGenerator">The generator to use for id value generation.</param> public IdentifierProperty( IType type, bool embedded, Cascades.IdentifierValue unsavedValue, IIdentifierGenerator identifierGenerator) : base(null, null, type) { this.isVirtual = true; this.embedded = embedded; this.unsavedValue = unsavedValue; this.identifierGenerator = identifierGenerator; this.identifierAssignedByInsert = identifierGenerator is IdentityGenerator; // TODO H3: identifierGenerator is PostInsertIdentifierGenerator; }
public ComponentType(System.Type componentClass, string[] propertyNames, IGetter[] propertyGetters, ISetter[] propertySetters, // currently not used, see the comment near the end of the method body bool foundCustomAcessor, IType[] propertyTypes, bool[] nullabilities, FetchMode[] joinedFetch, Cascades.CascadeStyle[] cascade, string parentProperty) { this.componentClass = componentClass; this.propertyTypes = propertyTypes; this.propertyNullability = nullabilities; propertySpan = propertyNames.Length; getters = propertyGetters; setters = propertySetters; string[] getterNames = new string[propertySpan]; string[] setterNames = new string[propertySpan]; System.Type[] propTypes = new System.Type[propertySpan]; for (int i = 0; i < propertySpan; i++) { getterNames[i] = getters[i].PropertyName; setterNames[i] = setters[i].PropertyName; propTypes[i] = getters[i].ReturnType; } if (parentProperty == null) { parentSetter = null; parentGetter = null; } else { IPropertyAccessor pa = PropertyAccessorFactory.GetPropertyAccessor(null); parentSetter = pa.GetSetter(componentClass, parentProperty); parentGetter = pa.GetGetter(componentClass, parentProperty); } this.propertyNames = propertyNames; this.cascade = cascade; this.joinedFetch = joinedFetch; if (Environment.UseReflectionOptimizer) { // NH: reflection optimizer works with custom accessors this.optimizer = Environment.BytecodeProvider.GetReflectionOptimizer(componentClass, getters, setters); } }
public DynamicComponentType( string[] propertyNames, IType[] propertyTypes, bool[] nullabilities, FetchMode[] joinedFetch, Cascades.CascadeStyle[] cascade ) { this.propertyNames = propertyNames; this.propertyTypes = propertyTypes; this.propertyNullability = nullabilities; this.joinedFetch = joinedFetch; this.cascade = cascade; propertySpan = propertyTypes.Length; }
/// <summary> /// Constructs VersionProperty instances. /// </summary> /// <param name="name">The name by which the property can be referenced within /// its owner.</param> /// <param name="node">The node name to use for XML-based representation of this /// property.</param> /// <param name="type">The Hibernate Type of this property.</param> /// <param name="lazy">Should this property be handled lazily?</param> /// <param name="insertable">Is this property an insertable value?</param> /// <param name="updateable">Is this property an updateable value?</param> /// <param name="insertGenerated">Is this property generated in the database on insert?</param> /// <param name="updateGenerated">Is this property generated in the database on update?</param> /// <param name="nullable">Is this property a nullable value?</param> /// <param name="checkable">Is this property a checkable value?</param> /// <param name="versionable">Is this property a versionable value?</param> /// <param name="cascadeStyle">The cascade style for this property's value.</param> /// <param name="unsavedValue">The value which, if found as the value of /// this (i.e., the version) property, represents new (i.e., un-saved) /// instances of the owning entity.</param> public VersionProperty( string name, string node, IType type, bool lazy, bool insertable, bool updateable, bool insertGenerated, bool updateGenerated, bool nullable, bool checkable, bool versionable, Cascades.CascadeStyle cascadeStyle, Cascades.VersionValue unsavedValue) : base( name, node, type, lazy, insertable, updateable, insertGenerated, updateGenerated, nullable, checkable, versionable, cascadeStyle) { this.unsavedValue = unsavedValue; }
private object SaveWithGeneratedIdentifier( object obj, Cascades.CascadingAction action, object anything ) { IClassPersister persister = GetPersister( obj ); try { object id = persister.IdentifierGenerator.Generate( this, obj ); if( id == null ) { throw new IdentifierGenerationException( string.Format( "null id generated for: {0}", obj.GetType().FullName ) ); } else if( id == IdentifierGeneratorFactory.ShortCircuitIndicator ) { return GetIdentifier( obj ); //yick!! } else if( id == IdentifierGeneratorFactory.IdentityColumnIndicator ) { return DoSave( obj, null, persister, true, action, anything ); } else { if( log.IsDebugEnabled ) { log.Debug( string.Format( "generated identifier: {0}", id ) ); } return DoSave( obj, id, persister, false, action, anything ); } } catch( HibernateException ) { // Do not call Convert on HibernateExceptions throw; } catch( Exception ex ) { throw Convert( ex, "Could not save object" ); } }
protected override bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config, Cascades.CascadeStyle cascadeStyle) { return (type.IsEntityType || type.IsCollectionType) && (cascadeStyle == null || cascadeStyle.DoCascade(cascadeAction)); }
private object DoSave( object theObj, Key key, IClassPersister persister, bool replicate, bool useIdentityColumn, Cascades.CascadingAction cascadeAction, object anything ) { if( persister.ImplementsValidatable ) { ( ( IValidatable ) theObj ).Validate(); } object id; if( useIdentityColumn ) { id = null; ExecuteInserts(); } else { id = key.Identifier; } // Put a placeholder in entries, so we don't recurse back to try and Save() the // same object again. QUESTION: Should this be done before OnSave() is called? // likewise, should it be done before OnUpdate()? AddEntry( theObj, Status.Saving, null, id, null, LockMode.Write, useIdentityColumn, persister, false ); // okay if id is null here // cascade-save to many-to-one BEFORE the parent is saved cascading++; try { Cascades.Cascade( this, persister, theObj, cascadeAction, CascadePoint.CascadeBeforeInsertAfterDelete, anything ); } finally { cascading--; } object[ ] values = persister.GetPropertyValues( theObj ); IType[ ] types = persister.PropertyTypes; bool substitute = false; if( !replicate ) { substitute = interceptor.OnSave( theObj, id, values, persister.PropertyNames, types ); // Keep the existing version number in the case of replicate! if( persister.IsVersioned ) { // IsUnsavedVersion bit below is NHibernate-specific substitute = Versioning.SeedVersion( values, persister.VersionProperty, persister.VersionType, persister.IsUnsavedVersion( values ) ) || substitute; } } if( persister.HasCollections ) { // TODO: make OnReplicateVisitor extend WrapVisitor if( replicate ) { OnReplicateVisitor visitor = new OnReplicateVisitor( this, id ); visitor.ProcessValues( values, types ); } WrapVisitor visitor2 = new WrapVisitor( this ); // substitutes into values by side-effect visitor2.ProcessValues( values, types ); substitute = substitute || visitor2.IsSubstitutionRequired; } if( substitute ) { persister.SetPropertyValues( theObj, values ); } TypeFactory.DeepCopy( values, types, persister.PropertyUpdateability, values ); NullifyTransientReferences( values, types, useIdentityColumn, theObj ); CheckNullability( values, persister, false ); if( useIdentityColumn ) { ScheduledIdentityInsertion insert = new ScheduledIdentityInsertion( values, theObj, persister, this ); Execute( insert ); id = insert.GeneratedId; persister.SetIdentifier( theObj, id ); key = new Key( id, persister ); CheckUniqueness( key, theObj ); } object version = Versioning.GetVersion( values, persister ); AddEntity( key, theObj ); AddEntry( theObj, Status.Loaded, values, id, version, LockMode.Write, useIdentityColumn, persister, replicate ); nonExists.Remove( key ); if( !useIdentityColumn ) { insertions.Add( new ScheduledInsertion( id, values, theObj, version, persister, this ) ); } // cascade-save to collections AFTER the collection owner was saved cascading++; try { Cascades.Cascade( this, persister, theObj, cascadeAction, CascadePoint.CascadeAfterInsertBeforeDelete, anything ); } finally { cascading--; } return id; }
/// <summary> /// Get the join type (inner, outer, etc) or -1 if the /// association should not be joined. Override on /// subclasses. /// </summary> protected virtual JoinType GetJoinType( IAssociationType type, FetchMode config, String path, String lhsTable, String[] lhsColumns, bool nullable, int currentDepth, Cascades.CascadeStyle cascadeStyle) { if (!IsJoinedFetchEnabled(type, config, cascadeStyle)) { return JoinType.None; } if (IsTooDeep(currentDepth) || IsTooManyCollections()) { return JoinType.None; } bool dupe = IsDuplicateAssociation(lhsTable, lhsColumns, type); if (dupe) { return JoinType.None; } return GetJoinType(nullable, currentDepth); }
/// <summary> /// We can use an inner join for first many-to-many association /// </summary> protected JoinType GetJoinType( IAssociationType type, FetchMode config, String path, ISet visitedAssociations, string lhsTable, string[] lhsColumns, bool nullable, int currentDepth, Cascades.CascadeStyle cascadeStyle) { JoinType joinType = base.GetJoinType( type, config, path, lhsTable, lhsColumns, nullable, currentDepth, cascadeStyle ); //we can use an inner join for the many-to-many if (joinType == JoinType.LeftOuterJoin && "".Equals(path)) { joinType = JoinType.InnerJoin; } return joinType; }
/// <summary> /// The superclass deliberately excludes collections /// </summary> protected override bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config, Cascades.CascadeStyle cascadeStyle) { return IsJoinedFetchEnabledInMapping(config, type); }
private object DoSave( object obj, object id, IClassPersister persister, bool useIdentityColumn, Cascades.CascadingAction cascadeAction, object anything ) { if( log.IsDebugEnabled ) { log.Debug( "saving " + MessageHelper.InfoString( persister, id ) ); } Key key; if( useIdentityColumn ) { // if the id is generated by the database, we assign the key later key = null; } else { key = new Key( id, persister ); object old = GetEntity( key ); if( old != null ) { EntityEntry e = GetEntry( old ); if( e.Status == Status.Deleted ) { ForceFlush( e ); } else { throw new NonUniqueObjectException( id, persister.MappedClass ); } } persister.SetIdentifier( obj, id ); } // Sub-insertions should occur before containing insertsion so // Try to do the callback not if( persister.ImplementsLifecycle ) { log.Debug( "calling OnSave()" ); if( ( ( ILifecycle ) obj ).OnSave( this ) == LifecycleVeto.Veto ) { log.Debug( "insertion vetoed by OnSave()" ); return id; } } return DoSave( obj, key, persister, false, useIdentityColumn, cascadeAction, anything ); }
public override ICollection CascadableChildrenCollection(PersistentCollectionType collectionType, object collection) { return(Cascades.GetLoadedElementsCollection(collectionType, collection)); }
public override ICollection CascadableChildrenCollection(PersistentCollectionType collectionType, object collection) { // saves / updates don't cascade to uninitialized collections return(Cascades.GetLoadedElementsCollection(collectionType, collection)); }
/// <summary> /// Override on subclasses to enable or suppress joining /// of certain association types /// </summary> protected virtual bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config, Cascades.CascadeStyle cascadeStyle) { return type.IsEntityType && IsJoinedFetchEnabledInMapping(config, type); }