public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { ConstructorInfo pc; try { pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs); } catch (Exception e) { throw new MappingException("Could not get constructor for " + persisterClass.Name, e); } try { return((ICollectionPersister)pc.Invoke(new object[] { model, cache, factory })); } catch (TargetInvocationException tie) { Exception e = tie.InnerException; if (e is HibernateException) { throw e; } else { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } } catch (Exception e) { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } }
/// <summary> /// Creates a specific Persister - could be a built in or custom persister. /// </summary> public static IEntityPersister Create(System.Type persisterClass, PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) { ConstructorInfo pc; try { pc = persisterClass.GetConstructor(PersisterConstructorArgs); } catch (Exception e) { throw new MappingException("Could not get constructor for " + persisterClass.Name, e); } try { return (IEntityPersister) pc.Invoke(new object[] {model, cache, factory, cfg}); } catch (TargetInvocationException tie) { Exception e = tie.InnerException; if (e is HibernateException) { throw e; } else { throw new MappingException("Could not instantiate persister " + persisterClass.Name, e); } } catch (Exception e) { throw new MappingException("Could not instantiate persister " + persisterClass.Name, e); } }
public BasicCollectionPersister( Mapping.Collection collection, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) : base(collection, cache, factory) { }
public OneToManyPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) { cascadeDeleteEnabled = collection.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete; keyIsNullable = collection.Key.IsNullable; keyIsUpdateable = collection.Key.IsUpdateable; }
public OneToManyPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) { _cascadeDeleteEnabled = collection.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete; _keyIsNullable = collection.Key.IsNullable; _keyIsUpdateable = collection.Key.IsUpdateable; }
/// <summary> /// Attempt to retrieve multiple objects from the Cache /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time</param> /// <returns>An array of cached objects or <see langword="null" /></returns> /// <exception cref="CacheException"></exception> public static object[] GetMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp) { if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache)) { throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching"); } return(batchableCache.GetMany(keys, timestamp)); }
/// <summary> /// Attempt to retrieve multiple objects from the Cache /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time</param> /// <returns>An array of cached objects or <see langword="null" /></returns> /// <exception cref="CacheException"></exception> public static object[] GetMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp) { // PreferMultipleGet yields false if !IBatchableCacheConcurrencyStrategy, no GetMany call should be done // in such case. return(ReflectHelper .CastOrThrow <IBatchableCacheConcurrencyStrategy>(cache, "batching") .GetMany(keys, timestamp)); }
public DiscriminatedSubclassWithDynamicComponentEntityPersister( PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory, mapping) { }
// 6.0 TODO: remove internal static bool PreferMultipleGet(this ICacheConcurrencyStrategy cache) { if (cache is IBatchableCacheConcurrencyStrategy batchableCache) { return(batchableCache.Cache.PreferMultipleGet); } return(false); }
// 6.0 TODO: remove internal static CacheBase GetCacheBase(this ICacheConcurrencyStrategy cache) { if (cache is IBatchableCacheConcurrencyStrategy batchableCache) { return(batchableCache.Cache); } return(cache.Cache?.AsCacheBase()); }
/// <summary> /// Associates the class name with the cache strategy. /// </summary> /// <param name="name">The classname of the class to cache.</param> /// <param name="cache">The <see cref="ICacheConcurrencyStrategy"/> to use for caching.</param> /// <exception cref="MappingException">Thrown when <c>name</c> already has a <c>cache</c> associated with it.</exception> public void AddCache( string name, ICacheConcurrencyStrategy cache ) { object old = caches[ name ]; if( old != null ) { throw new MappingException( "duplicate cache region" ); } caches[ name ] = cache; }
/// <summary> /// Attempt to cache objects, after loading them from the database. /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to put in the Cache.</param> /// <param name="values">The objects to put in the cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time.</param> /// <param name="versions">The version numbers of the objects we are putting.</param> /// <param name="versionComparers">The comparers to be used to compare version numbers</param> /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param> /// <returns><see langword="true" /> if the objects were successfully cached.</returns> /// <exception cref="CacheException"></exception> public static bool[] PutMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp, object[] versions, IComparer[] versionComparers, bool[] minimalPuts) { if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache)) { throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching"); } return(batchableCache.PutMany(keys, values, timestamp, versions, versionComparers, minimalPuts)); }
/// <summary> /// Associates the class name with the cache strategy. /// </summary> /// <param name="name">The classname of the class to cache.</param> /// <param name="cache">The <see cref="ICacheConcurrencyStrategy"/> to use for caching.</param> /// <exception cref="MappingException">Thrown when <c>name</c> already has a <c>cache</c> associated with it.</exception> public void AddCache(string name, ICacheConcurrencyStrategy cache) { object old = caches[name]; if (old != null) { throw new MappingException("duplicate cache region"); } caches[name] = cache; }
private void DoTestMinValueTimestampOnStrategy(ICache cache, ICacheConcurrencyStrategy strategy) { CacheKey key = CreateCacheKey("key"); strategy.Cache = cache; strategy.Put(key, "value", long.MinValue, 0, null, false); Assert.IsNull(strategy.Get(key, long.MinValue), "{0} strategy fails the test", strategy.GetType()); Assert.IsNull(strategy.Get(key, long.MaxValue), "{0} strategy fails the test", strategy.GetType()); }
private async Task DoTestMinValueTimestampOnStrategyAsync(ICache cache, ICacheConcurrencyStrategy strategy, CancellationToken cancellationToken = default(CancellationToken)) { CacheKey key = CreateCacheKey("key"); strategy.Cache = cache; await(strategy.PutAsync(key, "value", long.MinValue, 0, null, false, cancellationToken)); Assert.IsNull(await(strategy.GetAsync(key, long.MinValue, cancellationToken)), "{0} strategy fails the test", strategy.GetType()); Assert.IsNull(await(strategy.GetAsync(key, long.MaxValue, cancellationToken)), "{0} strategy fails the test", strategy.GetType()); }
private void AddToBatch(ICacheConcurrencyStrategy cache, CachePutData data) { if (!_putBatches.TryGetValue(cache, out var cachePutBatch)) { cachePutBatch = new CachePutBatch(_session, cache); _putBatches.Add(cache, cachePutBatch); } cachePutBatch.Add(data); }
public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, Configuration cfg) { ConstructorInfo pc; var use4Parameters = false; try { pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs); if (pc == null) { use4Parameters = true; pc = persisterClass.GetConstructor(CollectionPersisterConstructor2Args); } } catch (Exception e) { throw new MappingException("Could not get constructor for " + persisterClass.Name, e); } if (pc == null) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Could not find a public constructor for " + persisterClass.Name + ";"); messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructorArgs.Length + " parameters of types (in order):"); System.Array.ForEach(CollectionPersisterConstructorArgs, t => messageBuilder.AppendLine(t.FullName)); messageBuilder.AppendLine(); messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructor2Args.Length + " parameters of types (in order):"); System.Array.ForEach(CollectionPersisterConstructor2Args, t => messageBuilder.AppendLine(t.FullName)); throw new MappingException(messageBuilder.ToString()); } try { if (!use4Parameters) { return((ICollectionPersister)pc.Invoke(new object[] { model, cache, factory })); } return((ICollectionPersister)pc.Invoke(new object[] { model, cache, cfg, factory })); } catch (TargetInvocationException tie) { Exception e = tie.InnerException; if (e is HibernateException) { throw e; } else { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } } catch (Exception e) { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } }
/// <summary> /// Attempt to retrieve multiple objects from the Cache /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>An array of cached objects or <see langword="null" /></returns> /// <exception cref="CacheException"></exception> public static Task <object[]> GetManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp, CancellationToken cancellationToken) { if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache)) { throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching"); } if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <object[]>(cancellationToken)); } return(batchableCache.GetManyAsync(keys, timestamp, cancellationToken)); }
/// <summary> /// Attempt to cache objects, after loading them from the database. /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to put in the Cache.</param> /// <param name="values">The objects to put in the cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time.</param> /// <param name="versions">The version numbers of the objects we are putting.</param> /// <param name="versionComparers">The comparers to be used to compare version numbers</param> /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns><see langword="true" /> if the objects were successfully cached.</returns> /// <exception cref="CacheException"></exception> public static Task <bool[]> PutManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp, object[] versions, IComparer[] versionComparers, bool[] minimalPuts, CancellationToken cancellationToken) { if (!(cache is IBatchableCacheConcurrencyStrategy batchableCache)) { throw new InvalidOperationException($"Cache concurrency strategy {cache.GetType()} does not support batching"); } if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <bool[]>(cancellationToken)); } return(batchableCache.PutManyAsync(keys, values, timestamp, versions, versionComparers, minimalPuts, cancellationToken)); }
// 6.0 TODO: remove internal static CacheBase GetCacheBase(this ICacheConcurrencyStrategy cache) { if (cache is IBatchableCacheConcurrencyStrategy batchableCache) { return(batchableCache.Cache); } var concreteCache = cache.Cache; if (concreteCache == null) { return(null); } return(concreteCache as CacheBase ?? new ObsoleteCacheWrapper(concreteCache)); }
public static ICollectionPersister CreateCollectionPersister(Mapping.Collection model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { System.Type persisterClass = model.CollectionPersisterClass; if (persisterClass == null) { // default behaviour return model.IsOneToMany ? (ICollectionPersister) new OneToManyPersister(model, cache, factory) : (ICollectionPersister) new BasicCollectionPersister(model, cache, factory); } else { return Create(persisterClass, model, cache, factory); } }
/// <summary> /// Attempt to cache objects, after loading them from the database. /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to put in the Cache.</param> /// <param name="values">The objects to put in the cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time.</param> /// <param name="versions">The version numbers of the objects we are putting.</param> /// <param name="versionComparers">The comparers to be used to compare version numbers</param> /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param> /// <returns><see langword="true" /> if the objects were successfully cached.</returns> /// <exception cref="CacheException"></exception> public static bool[] PutMany(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp, object[] versions, IComparer[] versionComparers, bool[] minimalPuts) { if (cache is IBatchableCacheConcurrencyStrategy batchableCache) { return(batchableCache.PutMany(keys, values, timestamp, versions, versionComparers, minimalPuts)); } var result = new bool[keys.Length]; for (var i = 0; i < keys.Length; i++) { result[i] = cache.Put(keys[i], values[i], timestamp, versions[i], versionComparers[i], minimalPuts[i]); } return(result); }
/// <summary> /// Creates a built in Entity Persister or a custom Persister. /// </summary> public static IEntityPersister CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) { System.Type persisterClass = model.ClassPersisterClass; if (persisterClass == null || persisterClass == typeof(SingleTableEntityPersister)) { return new SingleTableEntityPersister(model, cache, factory, cfg); } else if (persisterClass == typeof(JoinedSubclassEntityPersister)) { return new JoinedSubclassEntityPersister(model, cache, factory, cfg); } else { return Create(persisterClass, model, cache, factory, cfg); } }
/// <summary> /// Attempt to cache objects, after loading them from the database. /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to put in the Cache.</param> /// <param name="values">The objects to put in the cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time.</param> /// <param name="versions">The version numbers of the objects we are putting.</param> /// <param name="versionComparers">The comparers to be used to compare version numbers</param> /// <param name="minimalPuts">Indicates that the cache should avoid a put if the item is already cached.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns><see langword="true" /> if the objects were successfully cached.</returns> /// <exception cref="CacheException"></exception> public static async Task <bool[]> PutManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, object[] values, long timestamp, object[] versions, IComparer[] versionComparers, bool[] minimalPuts, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (cache is IBatchableCacheConcurrencyStrategy batchableCache) { return(await(batchableCache.PutManyAsync(keys, values, timestamp, versions, versionComparers, minimalPuts, cancellationToken)).ConfigureAwait(false)); } var result = new bool[keys.Length]; for (var i = 0; i < keys.Length; i++) { result[i] = await(cache.PutAsync(keys[i], values[i], timestamp, versions[i], versionComparers[i], minimalPuts[i], cancellationToken)).ConfigureAwait(false); } return(result); }
/// <summary> /// Attempt to retrieve multiple objects from the Cache /// </summary> /// <param name="cache">The cache concurrency strategy.</param> /// <param name="keys">The keys (id) of the objects to get out of the Cache.</param> /// <param name="timestamp">A timestamp prior to the transaction start time</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>An array of cached objects or <see langword="null" /></returns> /// <exception cref="CacheException"></exception> public static Task <object[]> GetManyAsync(this ICacheConcurrencyStrategy cache, CacheKey[] keys, long timestamp, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <object[]>(cancellationToken)); } try { // PreferMultipleGet yields false if !IBatchableCacheConcurrencyStrategy, no GetMany call should be done // in such case. return(ReflectHelper .CastOrThrow <IBatchableCacheConcurrencyStrategy>(cache, "batching") .GetManyAsync(keys, timestamp, cancellationToken)); } catch (System.Exception ex) { return(Task.FromException <object[]>(ex)); } }
/// <summary> /// Creates a built in Entity Persister or a custom Persister. /// </summary> public static IEntityPersister CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) { System.Type persisterClass = model.EntityPersisterClass; if (persisterClass == null || persisterClass == typeof(SingleTableEntityPersister)) { return(new SingleTableEntityPersister(model, cache, factory, cfg)); } else if (persisterClass == typeof(JoinedSubclassEntityPersister)) { return(new JoinedSubclassEntityPersister(model, cache, factory, cfg)); } else if (persisterClass == typeof(UnionSubclassEntityPersister)) { return(new UnionSubclassEntityPersister(model, cache, factory, cfg)); } else { return(Create(persisterClass, model, cache, factory, cfg)); } }
/// <summary> /// Creates an <see cref="ICacheConcurrencyStrategy"/> from the parameters. /// </summary> /// <param name="usage">The name of the strategy that <see cref="ICacheProvider"/> should use for the class.</param> /// <param name="name">The name of the class the strategy is being created for.</param> /// <param name="mutable"><c>true</c> if the object being stored in the cache is mutable.</param> /// <returns>An <see cref="ICacheConcurrencyStrategy"/> to use for this object in the <see cref="ICache"/>.</returns> // was private in h2.1 public static ICacheConcurrencyStrategy CreateCache(string usage, string name, bool mutable) { if (log.IsDebugEnabled) { log.Debug(string.Format("cache for: {0} usage strategy: {1}", name, usage)); } ICacheConcurrencyStrategy ccs = null; switch (usage) { case CacheFactory.ReadOnly: if (mutable) { log.Warn("read-only cache configured for mutable: " + name); } ccs = new ReadOnlyCache(); break; case CacheFactory.ReadWrite: ccs = new ReadWriteCache(); break; case CacheFactory.NonstrictReadWrite: ccs = new NonstrictReadWriteCache(); break; //case CacheFactory.Transactional: // ccs = new TransactionalCache(); // break; default: throw new MappingException("cache usage attribute should be read-write, read-only, nonstrict-read-write, or transactional"); } return(ccs); }
/// <summary> /// Creates a specific Persister - could be a built in or custom persister. /// </summary> public static IEntityPersister Create(System.Type persisterClass, PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) { ConstructorInfo pc; try { pc = persisterClass.GetConstructor(PersisterConstructorArgs); } catch (Exception e) { throw new MappingException("Could not get constructor for " + persisterClass.Name, e); } try { return((IEntityPersister)pc.Invoke(new object[] { model, cache, factory, cfg })); } catch (TargetInvocationException tie) { Exception e = tie.InnerException; if (e is HibernateException) { throw ReflectHelper.UnwrapTargetInvocationException(tie); } else { throw new MappingException("Could not instantiate persister " + persisterClass.Name, e); } } catch (Exception e) { throw new MappingException("Could not instantiate persister " + persisterClass.Name, e); } }
public MyCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) {}
/// <summary> /// Constructs the NormalizedEntityPerister for the PersistentClass. /// </summary> /// <param name="persistentClass">The PersistentClass to create the EntityPersister for.</param> /// <param name="cache">The configured <see cref="ICacheConcurrencyStrategy" />.</param> /// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param> /// <param name="mapping">The mapping used to retrieve type information.</param> public JoinedSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory) { #region DISCRIMINATOR if (persistentClass.IsPolymorphic) { try { discriminatorValue = persistentClass.SubclassId; discriminatorSQLString = discriminatorValue.ToString(); } catch (Exception e) { throw new MappingException("Could not format discriminator value to SQL string", e); } } else { discriminatorValue = null; discriminatorSQLString = null; } if (OptimisticLockMode > Versioning.OptimisticLock.Version) throw new MappingException(string.Format("optimistic-lock=all|dirty not supported for joined-subclass mappings [{0}]", EntityName)); #endregion #region MULTITABLES int idColumnSpan = IdentifierColumnSpan; List<string> tables = new List<string>(); List<string[]> keyColumns = new List<string[]>(); List<bool> cascadeDeletes = new List<bool>(); IEnumerator<IKeyValue> kiter = persistentClass.KeyClosureIterator.GetEnumerator(); foreach (Table tab in persistentClass.TableClosureIterator) { kiter.MoveNext(); IKeyValue key = kiter.Current; string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); tables.Add(tabname); List<string> keyCols = new List<string>(idColumnSpan); IEnumerable<Column> enumerableKCols = new SafetyEnumerable<Column>(key.ColumnIterator); foreach (Column kcol in enumerableKCols) keyCols.Add(kcol.GetQuotedName(factory.Dialect)); keyColumns.Add(keyCols.ToArray()); cascadeDeletes.Add(key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete); } naturalOrderTableNames = tables.ToArray(); naturalOrderTableKeyColumns = keyColumns.ToArray(); naturalOrderCascadeDeleteEnabled = cascadeDeletes.ToArray(); List<string> subtables = new List<string>(); List<bool> isConcretes = new List<bool>(); keyColumns = new List<string[]>(); foreach (Table tab in persistentClass.SubclassTableClosureIterator) { isConcretes.Add(persistentClass.IsClassOrSuperclassTable(tab)); string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); subtables.Add(tabname); List<string> key = new List<string>(idColumnSpan); foreach (Column column in tab.PrimaryKey.ColumnIterator) key.Add(column.GetQuotedName(factory.Dialect)); keyColumns.Add(key.ToArray()); } subclassTableNameClosure = subtables.ToArray(); subclassTableKeyColumnClosure = keyColumns.ToArray(); isClassOrSuperclassTable = isConcretes.ToArray(); constraintOrderedTableNames = new string[subclassTableNameClosure.Length]; constraintOrderedKeyColumnNames = new string[subclassTableNameClosure.Length][]; int currentPosition = 0; for (int i = subclassTableNameClosure.Length - 1; i >= 0; i--, currentPosition++) { constraintOrderedTableNames[currentPosition] = subclassTableNameClosure[i]; constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i]; } tableSpan = naturalOrderTableNames.Length; tableNames = Reverse(naturalOrderTableNames); tableKeyColumns = Reverse(naturalOrderTableKeyColumns); Reverse(subclassTableNameClosure, tableSpan); Reverse(subclassTableKeyColumnClosure, tableSpan); spaces = ArrayHelper.Join(tableNames, persistentClass.SynchronizedTables.ToArray()); // Custom sql customSQLInsert = new SqlString[tableSpan]; customSQLUpdate = new SqlString[tableSpan]; customSQLDelete = new SqlString[tableSpan]; insertCallable = new bool[tableSpan]; updateCallable = new bool[tableSpan]; deleteCallable = new bool[tableSpan]; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; PersistentClass pc = persistentClass; int jk = tableSpan - 1; while (pc != null) { customSQLInsert[jk] = pc.CustomSQLInsert; insertCallable[jk] = customSQLInsert[jk] != null && pc.IsCustomInsertCallable; insertResultCheckStyles[jk] = pc.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[jk], insertCallable[jk]); customSQLUpdate[jk] = pc.CustomSQLUpdate; updateCallable[jk] = customSQLUpdate[jk] != null && pc.IsCustomUpdateCallable; updateResultCheckStyles[jk] = pc.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[jk], updateCallable[jk]); customSQLDelete[jk] = pc.CustomSQLDelete; deleteCallable[jk] = customSQLDelete[jk] != null && pc.IsCustomDeleteCallable; deleteResultCheckStyles[jk] = pc.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[jk], deleteCallable[jk]); jk--; pc = pc.Superclass; } if (jk != -1) { throw new AssertionFailure("Tablespan does not match height of joined-subclass hierarchy."); } #endregion #region PROPERTIES int hydrateSpan = PropertySpan; naturalOrderPropertyTableNumbers = new int[hydrateSpan]; propertyTableNumbers = new int[hydrateSpan]; int i2 = 0; foreach (Property prop in persistentClass.PropertyClosureIterator) { string tabname = prop.Value.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); propertyTableNumbers[i2] = GetTableId(tabname, tableNames); naturalOrderPropertyTableNumbers[i2] = GetTableId(tabname, naturalOrderTableNames); i2++; } // subclass closure properties List<int> columnTableNumbers = new List<int>(); List<int> formulaTableNumbers = new List<int>(); List<int> propTableNumbers = new List<int>(); foreach (Property prop in persistentClass.SubclassPropertyClosureIterator) { Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); int tabnum = GetTableId(tabname, subclassTableNameClosure); propTableNumbers.Add(tabnum); foreach (ISelectable thing in prop.ColumnIterator) { if (thing.IsFormula) formulaTableNumbers.Add(tabnum); else columnTableNumbers.Add(tabnum); } } subclassColumnTableNumberClosure = columnTableNumbers.ToArray(); subclassPropertyTableNumberClosure = propTableNumbers.ToArray(); subclassFormulaTableNumberClosure = formulaTableNumbers.ToArray(); #endregion #region SUBCLASSES int subclassSpan = persistentClass.SubclassSpan + 1; subclassClosure = new string[subclassSpan]; subclassClosure[subclassSpan - 1] = EntityName; if (persistentClass.IsPolymorphic) { subclassesByDiscriminatorValue[discriminatorValue] = EntityName; discriminatorValues = new string[subclassSpan]; discriminatorValues[subclassSpan - 1] = discriminatorSQLString; notNullColumnTableNumbers = new int[subclassSpan]; int id = GetTableId( persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName), subclassTableNameClosure); notNullColumnTableNumbers[subclassSpan - 1] = id; notNullColumnNames = new string[subclassSpan]; notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0]; //( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); } else { discriminatorValues = null; notNullColumnTableNumbers = null; notNullColumnNames = null; } int k2 = 0; foreach (Subclass sc in persistentClass.SubclassIterator) { subclassClosure[k2] = sc.EntityName; try { if (persistentClass.IsPolymorphic) { // we now use subclass ids that are consistent across all // persisters for a class hierarchy, so that the use of // "foo.class = Bar" works in HQL int subclassId = sc.SubclassId; //new Integer(k+1); subclassesByDiscriminatorValue[subclassId] = sc.EntityName; discriminatorValues[k2] = subclassId.ToString(); int id = GetTableId( sc.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName), subclassTableNameClosure); notNullColumnTableNumbers[k2] = id; notNullColumnNames[k2] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); } } catch (Exception e) { throw new MappingException("Error parsing discriminator value", e); } k2++; } #endregion InitLockers(); InitSubclassPropertyAliasesMap(persistentClass); PostConstruct(mapping); }
public BasicCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) { }
public AbstractCollectionPersister( Mapping.Collection collection, ISessionFactoryImplementor factory ) { this.factory = factory; dialect = factory.Dialect; //sqlExceptionConverter = factory.SQLExceptionConverter; collectionType = collection.CollectionType; role = collection.Role; ownerClass = collection.OwnerClass; Alias alias = new Alias( "__" ); sqlOrderByString = collection.OrderBy; hasOrder = sqlOrderByString != null; sqlOrderByStringTemplate = hasOrder ? Template.RenderOrderByStringTemplate( sqlOrderByString, dialect ) : null; sqlWhereString = collection.Where; hasWhere = sqlWhereString != null; sqlWhereStringTemplate = hasWhere ? Template.RenderWhereStringTemplate( sqlWhereString, dialect ) : null; hasOrphanDelete = collection.OrphanDelete; batchSize = collection.BatchSize; cache = collection.Cache; keyType = collection.Key.Type; int keySpan = collection.Key.ColumnSpan; keyColumnNames = new string[keySpan]; string[ ] keyAliases = new string[keySpan]; int k = 0; foreach( Column col in collection.Key.ColumnCollection ) { keyColumnNames[ k ] = col.GetQuotedName( dialect ); keyAliases[ k ] = col.Alias( dialect ); k++; } keyColumnAliases = alias.ToAliasStrings( keyAliases, dialect ); //unquotedKeyColumnNames = StringHelper.Unquote( keyColumnAliases ); ISet distinctColumns = new HashedSet(); CheckColumnDuplication( distinctColumns, collection.Key.ColumnCollection ); //isSet = collection.IsSet; //isSorted = collection.IsSorted; primitiveArray = collection.IsPrimitiveArray; array = collection.IsArray; IValue element = collection.Element; int elementSpan = element.ColumnSpan; ICollection iter = element.ColumnCollection; Table table = collection.CollectionTable; enableJoinedFetch = element.OuterJoinFetchSetting; elementType = element.Type; if( !collection.IsOneToMany ) { CheckColumnDuplication( distinctColumns, element.ColumnCollection ); } if( elementType.IsEntityType ) { elementPersister = factory.GetPersister( ( ( EntityType ) elementType ).AssociatedClass ); } else { elementPersister = null; } qualifiedTableName = table.GetQualifiedName( dialect, factory.DefaultSchema ); string[ ] aliases = new string[elementSpan]; elementColumnNames = new string[elementSpan]; int j = 0; foreach( Column col in iter ) { elementColumnNames[ j ] = col.GetQuotedName( dialect ); aliases[ j ] = col.Alias( dialect ); j++; } elementColumnAliases = alias.ToAliasStrings( aliases, dialect ); IType selectColumns; string[ ] selectType; hasIndex = collection.IsIndexed; if( hasIndex ) { IndexedCollection indexedCollection = ( IndexedCollection ) collection; indexType = indexedCollection.Index.Type; int indexSpan = indexedCollection.Index.ColumnSpan; indexColumnNames = new string[indexSpan]; string[ ] indexAliases = new string[indexSpan]; int i = 0; foreach( Column indexCol in indexedCollection.Index.ColumnCollection ) { indexAliases[ i ] = indexCol.Alias( dialect ); indexColumnNames[ i ] = indexCol.GetQuotedName( dialect ); i++; } selectType = indexColumnNames; selectColumns = indexType; indexColumnAliases = alias.ToAliasStrings( indexAliases, dialect ); CheckColumnDuplication( distinctColumns, indexedCollection.Index.ColumnCollection ); } else { indexType = null; indexColumnNames = null; indexColumnAliases = null; selectType = elementColumnNames; selectColumns = elementType; } hasIdentifier = collection.IsIdentified; if( hasIdentifier ) { if( collection.IsOneToMany ) { throw new MappingException( "one-to-many collections with identifiers are not supported." ); } IdentifierCollection idColl = ( IdentifierCollection ) collection; identifierType = idColl.Identifier.Type; Column col = null; foreach( Column column in idColl.Identifier.ColumnCollection ) { col = column; break; } identifierColumnName = col.GetQuotedName( dialect ); selectType = new string[ ] {identifierColumnName}; selectColumns = identifierType; identifierColumnAlias = alias.ToAliasString( col.Alias( dialect ), dialect ); unquotedIdentifierColumnName = identifierColumnAlias; identifierGenerator = idColl.Identifier.CreateIdentifierGenerator( dialect ); CheckColumnDuplication( distinctColumns, idColl.Identifier.ColumnCollection ); } else { identifierType = null; identifierColumnName = null; identifierColumnAlias = null; unquotedIdentifierColumnName = null; identifierGenerator = null; } rowSelectColumnNames = selectType; rowSelectType = selectColumns; sqlDeleteString = GenerateDeleteString(); sqlInsertRowString = GenerateInsertRowString(); sqlUpdateRowString = GenerateUpdateRowString(); sqlDeleteRowString = GenerateDeleteRowString(); isLazy = collection.IsLazy; isInverse = collection.IsInverse; if( collection.IsArray ) { elementClass = ( ( Array ) collection ).ElementClass; } else { // for non-arrays, we don't need to know the element class elementClass = null; } initializer = CreateCollectionInitializer( factory ); if( elementType.IsComponentType ) { elementPropertyMapping = new CompositeElementPropertyMapping( elementColumnNames, ( IAbstractComponentType ) elementType, factory ); } else if( !elementType.IsEntityType ) { elementPropertyMapping = new ElementPropertyMapping( elementColumnNames, elementType ); } else { IClassPersister persister = factory.GetPersister( ( ( EntityType ) elementType ).AssociatedClass ); // Not all classpersisters implement IPropertyMapping! if( persister is IPropertyMapping ) { elementPropertyMapping = ( IPropertyMapping ) persister; } else { elementPropertyMapping = new ElementPropertyMapping( elementColumnNames, elementType ); } } }
public CustomPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) { this.factory = factory; }
public UnionSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping):base(persistentClass, cache, factory) { if (IdentifierGenerator is IdentityGenerator) { throw new MappingException("Cannot use identity column key generation with <union-subclass> mapping for: " + EntityName); } // TABLE tableName = persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); #region Custom SQL SqlString sql; bool callable; ExecuteUpdateResultCheckStyle checkStyle; sql = persistentClass.CustomSQLInsert; callable = sql != null && persistentClass.IsCustomInsertCallable; checkStyle = sql == null ? ExecuteUpdateResultCheckStyle.Count : (persistentClass.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable)); customSQLInsert = new SqlString[] { sql }; insertCallable = new bool[] { callable }; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; sql = persistentClass.CustomSQLUpdate; callable = sql != null && persistentClass.IsCustomUpdateCallable; checkStyle = sql == null ? ExecuteUpdateResultCheckStyle.Count : (persistentClass.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable)); customSQLUpdate = new SqlString[] { sql }; updateCallable = new bool[] { callable }; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; sql = persistentClass.CustomSQLDelete; callable = sql != null && persistentClass.IsCustomDeleteCallable; checkStyle = sql == null ? ExecuteUpdateResultCheckStyle.Count : (persistentClass.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable)); customSQLDelete = new SqlString[] { sql }; deleteCallable = new bool[] { callable }; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; #endregion discriminatorValue = persistentClass.SubclassId; discriminatorSQLValue = persistentClass.SubclassId.ToString(); #region PROPERTIES int subclassSpan = persistentClass.SubclassSpan + 1; subclassClosure = new string[subclassSpan]; subclassClosure[0] = EntityName; #endregion #region SUBCLASSES subclassByDiscriminatorValue[persistentClass.SubclassId] = persistentClass.EntityName; if (persistentClass.IsPolymorphic) { int k = 1; foreach (Subclass sc in persistentClass.SubclassIterator) { subclassClosure[k++] = sc.EntityName; subclassByDiscriminatorValue[sc.SubclassId] = sc.EntityName; } } #endregion #region SPACES //TODO: i'm not sure, but perhaps we should exclude abstract denormalized tables? int spacesSize = 1 + persistentClass.SynchronizedTables.Count; spaces = new string[spacesSize]; spaces[0] = tableName; IEnumerator<string> iSyncTab = persistentClass.SynchronizedTables.GetEnumerator(); for (int i = 1; i < spacesSize; i++) { iSyncTab.MoveNext(); spaces[i] = iSyncTab.Current; } HashedSet<string> subclassTables = new HashedSet<string>(); foreach (Table table in persistentClass.SubclassTableClosureIterator) { subclassTables.Add( table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName)); } subclassSpaces = new string[subclassTables.Count]; subclassTables.CopyTo(subclassSpaces, 0); subquery = GenerateSubquery(persistentClass, mapping); if (IsMultiTable) { int idColumnSpan = IdentifierColumnSpan; List<string> tableNames = new List<string>(); List<string[]> keyColumns = new List<string[]>(); if (!IsAbstract) { tableNames.Add(tableName); keyColumns.Add(IdentifierColumnNames); } foreach (Table tab in persistentClass.SubclassTableClosureIterator) { if (!tab.IsAbstractUnionTable) { string _tableName = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); tableNames.Add(_tableName); List<string> key = new List<string>(idColumnSpan); foreach (Column column in tab.PrimaryKey.ColumnIterator) key.Add(column.GetQuotedName(factory.Dialect)); keyColumns.Add(key.ToArray()); } } constraintOrderedTableNames = tableNames.ToArray(); constraintOrderedKeyColumnNames = keyColumns.ToArray(); } else { constraintOrderedTableNames = new string[] { tableName }; constraintOrderedKeyColumnNames = new string[][] { IdentifierColumnNames }; } #endregion InitLockers(); InitSubclassPropertyAliasesMap(persistentClass); PostConstruct(mapping); }
public CachePutBatch(ISessionImplementor session, ICacheConcurrencyStrategy cacheConcurrencyStrategy) : base(session, cacheConcurrencyStrategy) { }
public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners) { Init(); log.Info("building session factory"); properties = new Dictionary <string, string>(cfg.Properties); interceptor = cfg.Interceptor; this.settings = settings; sqlFunctionRegistry = new SQLFunctionRegistry(settings.Dialect, cfg.SqlFunctions); eventListeners = listeners; filters = new Dictionary <string, FilterDefinition>(cfg.FilterDefinitions); if (log.IsDebugEnabled) { log.Debug("Session factory constructed with filter configurations : " + CollectionPrinter.ToString(filters)); } if (log.IsDebugEnabled) { log.Debug("instantiating session factory with properties: " + CollectionPrinter.ToString(properties)); } try { if (settings.IsKeywordsImportEnabled) { SchemaMetadataUpdater.Update(this); } if (settings.IsAutoQuoteEnabled) { SchemaMetadataUpdater.QuoteTableAndColumns(cfg); } } catch (NotSupportedException) { // Ignore if the Dialect does not provide DataBaseSchema } #region Caches settings.CacheProvider.Start(properties); #endregion #region Generators identifierGenerators = new Dictionary <string, IIdentifierGenerator>(); foreach (PersistentClass model in cfg.ClassMappings) { if (!model.IsInherited) { IIdentifierGenerator generator = model.Identifier.CreateIdentifierGenerator(settings.Dialect, settings.DefaultCatalogName, settings.DefaultSchemaName, (RootClass)model); identifierGenerators[model.EntityName] = generator; } } #endregion #region Persisters Dictionary <string, ICacheConcurrencyStrategy> caches = new Dictionary <string, ICacheConcurrencyStrategy>(); entityPersisters = new Dictionary <string, IEntityPersister>(); implementorToEntityName = new Dictionary <System.Type, string>(); Dictionary <string, IClassMetadata> classMeta = new Dictionary <string, IClassMetadata>(); foreach (PersistentClass model in cfg.ClassMappings) { model.PrepareTemporaryTables(mapping, settings.Dialect); string cacheRegion = model.RootClazz.CacheRegionName; ICacheConcurrencyStrategy cache; if (!caches.TryGetValue(cacheRegion, out cache)) { cache = CacheFactory.CreateCache(model.CacheConcurrencyStrategy, cacheRegion, model.IsMutable, settings, properties); if (cache != null) { caches.Add(cacheRegion, cache); allCacheRegions.Add(cache.RegionName, cache.Cache); } } IEntityPersister cp = PersisterFactory.CreateClassPersister(model, cache, this, mapping); entityPersisters[model.EntityName] = cp; classMeta[model.EntityName] = cp.ClassMetadata; if (model.HasPocoRepresentation) { implementorToEntityName[model.MappedClass] = model.EntityName; } } classMetadata = new UnmodifiableDictionary <string, IClassMetadata>(classMeta); Dictionary <string, ISet <string> > tmpEntityToCollectionRoleMap = new Dictionary <string, ISet <string> >(); collectionPersisters = new Dictionary <string, ICollectionPersister>(); foreach (Mapping.Collection model in cfg.CollectionMappings) { ICacheConcurrencyStrategy cache = CacheFactory.CreateCache(model.CacheConcurrencyStrategy, model.CacheRegionName, model.Owner.IsMutable, settings, properties); if (cache != null) { allCacheRegions[cache.RegionName] = cache.Cache; } ICollectionPersister persister = PersisterFactory.CreateCollectionPersister(cfg, model, cache, this); collectionPersisters[model.Role] = persister; IType indexType = persister.IndexType; if (indexType != null && indexType.IsAssociationType && !indexType.IsAnyType) { string entityName = ((IAssociationType)indexType).GetAssociatedEntityName(this); ISet <string> roles; if (!tmpEntityToCollectionRoleMap.TryGetValue(entityName, out roles)) { roles = new HashSet <string>(); tmpEntityToCollectionRoleMap[entityName] = roles; } roles.Add(persister.Role); } IType elementType = persister.ElementType; if (elementType.IsAssociationType && !elementType.IsAnyType) { string entityName = ((IAssociationType)elementType).GetAssociatedEntityName(this); ISet <string> roles; if (!tmpEntityToCollectionRoleMap.TryGetValue(entityName, out roles)) { roles = new HashSet <string>(); tmpEntityToCollectionRoleMap[entityName] = roles; } roles.Add(persister.Role); } } Dictionary <string, ICollectionMetadata> tmpcollectionMetadata = new Dictionary <string, ICollectionMetadata>(collectionPersisters.Count); foreach (KeyValuePair <string, ICollectionPersister> collectionPersister in collectionPersisters) { tmpcollectionMetadata.Add(collectionPersister.Key, collectionPersister.Value.CollectionMetadata); } collectionMetadata = new UnmodifiableDictionary <string, ICollectionMetadata>(tmpcollectionMetadata); collectionRolesByEntityParticipant = new UnmodifiableDictionary <string, ISet <string> >(tmpEntityToCollectionRoleMap); #endregion #region Named Queries namedQueries = new Dictionary <string, NamedQueryDefinition>(cfg.NamedQueries); namedSqlQueries = new Dictionary <string, NamedSQLQueryDefinition>(cfg.NamedSQLQueries); sqlResultSetMappings = new Dictionary <string, ResultSetMappingDefinition>(cfg.SqlResultSetMappings); #endregion imports = new Dictionary <string, string>(cfg.Imports); #region after *all* persisters and named queries are registered foreach (IEntityPersister persister in entityPersisters.Values) { persister.PostInstantiate(); } foreach (ICollectionPersister persister in collectionPersisters.Values) { persister.PostInstantiate(); } #endregion #region Serialization info name = settings.SessionFactoryName; try { uuid = (string)UuidGenerator.Generate(null, null); } catch (Exception) { throw new AssertionFailure("Could not generate UUID"); } SessionFactoryObjectFactory.AddInstance(uuid, name, this, properties); #endregion log.Debug("Instantiated session factory"); #region Schema management if (settings.IsAutoCreateSchema) { new SchemaExport(cfg).Create(false, true); } if (settings.IsAutoUpdateSchema) { new SchemaUpdate(cfg).Execute(false, true); } if (settings.IsAutoValidateSchema) { new SchemaValidator(cfg, settings).Validate(); } if (settings.IsAutoDropSchema) { schemaExport = new SchemaExport(cfg); } #endregion #region Obtaining TransactionManager // not ported yet #endregion currentSessionContext = BuildCurrentSessionContext(); if (settings.IsQueryCacheEnabled) { updateTimestampsCache = new UpdateTimestampsCache(settings, properties); queryCache = settings.QueryCacheFactory.GetQueryCache(null, updateTimestampsCache, settings, properties); queryCaches = new ThreadSafeDictionary <string, IQueryCache>(new Dictionary <string, IQueryCache>()); } else { updateTimestampsCache = null; queryCache = null; queryCaches = null; } #region Checking for named queries if (settings.IsNamedQueryStartupCheckingEnabled) { IDictionary <string, HibernateException> errors = CheckNamedQueries(); if (errors.Count > 0) { StringBuilder failingQueries = new StringBuilder("Errors in named queries: "); foreach (KeyValuePair <string, HibernateException> pair in errors) { failingQueries.Append('{').Append(pair.Key).Append('}'); log.Error("Error in named query: " + pair.Key, pair.Value); } throw new HibernateException(failingQueries.ToString()); } } #endregion Statistics.IsStatisticsEnabled = settings.IsStatisticsEnabled; // EntityNotFoundDelegate IEntityNotFoundDelegate enfd = cfg.EntityNotFoundDelegate; if (enfd == null) { enfd = new DefaultEntityNotFoundDelegate(); } entityNotFoundDelegate = enfd; }
/// <summary> /// Constructs the NormalizedEntityPerister for the PersistentClass. /// </summary> /// <param name="persistentClass">The PersistentClass to create the EntityPersister for.</param> /// <param name="cache">The configured <see cref="ICacheConcurrencyStrategy" />.</param> /// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param> /// <param name="mapping">The mapping used to retrieve type information.</param> public JoinedSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory) { #region DISCRIMINATOR if (persistentClass.IsPolymorphic) { try { discriminatorValue = persistentClass.SubclassId; discriminatorSQLString = discriminatorValue.ToString(); } catch (Exception e) { throw new MappingException("Could not format discriminator value to SQL string", e); } } else { discriminatorValue = null; discriminatorSQLString = null; } if (OptimisticLockMode > Versioning.OptimisticLock.Version) { throw new MappingException(string.Format("optimistic-lock=all|dirty not supported for joined-subclass mappings [{0}]", EntityName)); } #endregion #region MULTITABLES int idColumnSpan = IdentifierColumnSpan; List <string> tables = new List <string>(); List <string[]> keyColumns = new List <string[]>(); List <bool> cascadeDeletes = new List <bool>(); using (var kiter = persistentClass.KeyClosureIterator.GetEnumerator()) { foreach (var tab in persistentClass.TableClosureIterator) { kiter.MoveNext(); var key = kiter.Current; var tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); tables.Add(tabname); var keyCols = new List <string>(idColumnSpan); var enumerableKCols = new SafetyEnumerable <Column>(key.ColumnIterator); foreach (var kcol in enumerableKCols) { keyCols.Add(kcol.GetQuotedName(factory.Dialect)); } keyColumns.Add(keyCols.ToArray()); cascadeDeletes.Add(key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete); } } naturalOrderTableNames = tables.ToArray(); naturalOrderTableKeyColumns = keyColumns.ToArray(); naturalOrderCascadeDeleteEnabled = cascadeDeletes.ToArray(); List <string> subtables = new List <string>(); List <bool> isConcretes = new List <bool>(); keyColumns = new List <string[]>(); foreach (Table tab in persistentClass.SubclassTableClosureIterator) { isConcretes.Add(persistentClass.IsClassOrSuperclassTable(tab)); string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); subtables.Add(tabname); List <string> key = new List <string>(idColumnSpan); foreach (Column column in tab.PrimaryKey.ColumnIterator) { key.Add(column.GetQuotedName(factory.Dialect)); } keyColumns.Add(key.ToArray()); } subclassTableNameClosure = subtables.ToArray(); subclassTableKeyColumnClosure = keyColumns.ToArray(); isClassOrSuperclassTable = isConcretes.ToArray(); constraintOrderedTableNames = new string[subclassTableNameClosure.Length]; constraintOrderedKeyColumnNames = new string[subclassTableNameClosure.Length][]; int currentPosition = 0; for (int i = subclassTableNameClosure.Length - 1; i >= 0; i--, currentPosition++) { constraintOrderedTableNames[currentPosition] = subclassTableNameClosure[i]; constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i]; } tableSpan = naturalOrderTableNames.Length; tableNames = Reverse(naturalOrderTableNames); tableKeyColumns = Reverse(naturalOrderTableKeyColumns); Reverse(subclassTableNameClosure, tableSpan); Reverse(subclassTableKeyColumnClosure, tableSpan); spaces = ArrayHelper.Join(tableNames, persistentClass.SynchronizedTables.ToArray()); // Custom sql customSQLInsert = new SqlString[tableSpan]; customSQLUpdate = new SqlString[tableSpan]; customSQLDelete = new SqlString[tableSpan]; insertCallable = new bool[tableSpan]; updateCallable = new bool[tableSpan]; deleteCallable = new bool[tableSpan]; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; PersistentClass pc = persistentClass; int jk = tableSpan - 1; while (pc != null) { customSQLInsert[jk] = pc.CustomSQLInsert; insertCallable[jk] = customSQLInsert[jk] != null && pc.IsCustomInsertCallable; insertResultCheckStyles[jk] = pc.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[jk], insertCallable[jk]); customSQLUpdate[jk] = pc.CustomSQLUpdate; updateCallable[jk] = customSQLUpdate[jk] != null && pc.IsCustomUpdateCallable; updateResultCheckStyles[jk] = pc.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[jk], updateCallable[jk]); customSQLDelete[jk] = pc.CustomSQLDelete; deleteCallable[jk] = customSQLDelete[jk] != null && pc.IsCustomDeleteCallable; deleteResultCheckStyles[jk] = pc.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[jk], deleteCallable[jk]); jk--; pc = pc.Superclass; } if (jk != -1) { throw new AssertionFailure("Tablespan does not match height of joined-subclass hierarchy."); } #endregion #region PROPERTIES int hydrateSpan = PropertySpan; naturalOrderPropertyTableNumbers = new int[hydrateSpan]; propertyTableNumbers = new int[hydrateSpan]; int i2 = 0; foreach (Property prop in persistentClass.PropertyClosureIterator) { string tabname = prop.Value.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); propertyTableNumbers[i2] = GetTableId(tabname, tableNames); naturalOrderPropertyTableNumbers[i2] = GetTableId(tabname, naturalOrderTableNames); i2++; } // subclass closure properties List <int> columnTableNumbers = new List <int>(); List <int> formulaTableNumbers = new List <int>(); List <int> propTableNumbers = new List <int>(); foreach (Property prop in persistentClass.SubclassPropertyClosureIterator) { Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); int tabnum = GetTableId(tabname, subclassTableNameClosure); propTableNumbers.Add(tabnum); foreach (ISelectable thing in prop.ColumnIterator) { if (thing.IsFormula) { formulaTableNumbers.Add(tabnum); } else { columnTableNumbers.Add(tabnum); } } } subclassColumnTableNumberClosure = columnTableNumbers.ToArray(); subclassPropertyTableNumberClosure = propTableNumbers.ToArray(); subclassFormulaTableNumberClosure = formulaTableNumbers.ToArray(); #endregion #region SUBCLASSES int subclassSpan = persistentClass.SubclassSpan + 1; subclassClosure = new string[subclassSpan]; subclassClosure[subclassSpan - 1] = EntityName; if (persistentClass.IsPolymorphic) { subclassesByDiscriminatorValue[discriminatorValue] = EntityName; discriminatorValues = new string[subclassSpan]; discriminatorValues[subclassSpan - 1] = discriminatorSQLString; notNullColumnTableNumbers = new int[subclassSpan]; int id = GetTableId( persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName), subclassTableNameClosure); notNullColumnTableNumbers[subclassSpan - 1] = id; notNullColumnNames = new string[subclassSpan]; notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0]; //( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); } else { discriminatorValues = null; notNullColumnTableNumbers = null; notNullColumnNames = null; } int k2 = 0; foreach (Subclass sc in persistentClass.SubclassIterator) { subclassClosure[k2] = sc.EntityName; try { if (persistentClass.IsPolymorphic) { // we now use subclass ids that are consistent across all // persisters for a class hierarchy, so that the use of // "foo.class = Bar" works in HQL int subclassId = sc.SubclassId; //new Integer(k+1); subclassesByDiscriminatorValue[subclassId] = sc.EntityName; discriminatorValues[k2] = subclassId.ToString(); int id = GetTableId( sc.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName), subclassTableNameClosure); notNullColumnTableNumbers[k2] = id; notNullColumnNames[k2] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); } } catch (Exception e) { throw new MappingException("Error parsing discriminator value", e); } k2++; } #endregion InitLockers(); InitSubclassPropertyAliasesMap(persistentClass); PostConstruct(mapping); }
protected AbstractEntityPersister( PersistentClass model, ISessionFactoryImplementor factory ) { dialect = factory.Dialect; //sqlExceptionConverter = factory.SQLExceptionConverter; // CLASS className = model.MappedClass.FullName; rootClassName = model.RootClazz.Name; mappedClass = model.MappedClass; mutable = model.IsMutable; selectBeforeUpdate = model.SelectBeforeUpdate; dynamicUpdate = model.DynamicUpdate; dynamicInsert = model.DynamicInsert; sqlWhereString = model.Where; sqlWhereStringTemplate = sqlWhereString == null ? null : Template.RenderWhereStringTemplate( sqlWhereString, Dialect ); polymorphic = model.IsPolymorphic; explicitPolymorphism = model.IsExplicitPolymorphism; inherited = model.IsInherited; superclass = inherited ? model.Superclass.MappedClass : null; hasSubclasses = model.HasSubclasses; batchSize = model.BatchSize; constructor = ReflectHelper.GetDefaultConstructor( mappedClass ); abstractClass = ReflectHelper.IsAbstractClass( mappedClass ); entityType = NHibernateUtil.Entity( mappedClass ); optimisticLockMode = model.OptimisticLockMode; if( optimisticLockMode > OptimisticLockMode.Version && !dynamicUpdate ) { throw new MappingException( string.Format( "optimistic-lock setting requires dynamic-update=\'true\': {0}", className ) ); } // verify that the class has a default constructor if it is not abstract - it is considered // a mapping exception if the default ctor is missing. if( abstractClass == false && constructor == null ) { throw new MappingException( "The mapped class " + mappedClass.FullName + " must declare a default (no-arg) constructor." ); } // IDENTIFIER hasEmbeddedIdentifier = model.HasEmbeddedIdentifier; IValue idValue = model.Identifier; identifierType = idValue.Type; if( model.HasIdentifierProperty ) { Mapping.Property idProperty = model.IdentifierProperty; identifierPropertyName = idProperty.Name; identifierSetter = idProperty.GetSetter( mappedClass ); identifierGetter = idProperty.GetGetter( mappedClass ); } else { identifierPropertyName = null; identifierGetter = null; identifierSetter = null; } System.Type prox = model.ProxyInterface; MethodInfo proxySetIdentifierMethod = null; MethodInfo proxyGetIdentifierMethod = null; if( model.HasIdentifierProperty && prox != null ) { Mapping.Property idProperty = model.IdentifierProperty; PropertyInfo getIdPropertyInfo = idProperty.GetGetter( prox ).Property; if( getIdPropertyInfo != null ) { proxyGetIdentifierMethod = getIdPropertyInfo.GetGetMethod( true ); } PropertyInfo setIdPropertyInfo = idProperty.GetSetter( prox ).Property; if( setIdPropertyInfo != null ) { proxySetIdentifierMethod = setIdPropertyInfo.GetSetMethod( true ); } } // HYDRATE SPAN hydrateSpan = model.PropertyClosureCollection.Count; // IDENTIFIER int idColumnSpan = model.Identifier.ColumnSpan; identifierColumnNames = new string[idColumnSpan]; identifierAliases = new string[idColumnSpan]; int i = 0; foreach( Column col in idValue.ColumnCollection ) { identifierColumnNames[ i ] = col.GetQuotedName( Dialect ); identifierAliases[ i ] = col.Alias( Dialect ); i++; } // GENERATOR identifierGenerator = model.Identifier.CreateIdentifierGenerator( Dialect ); useIdentityColumn = identifierGenerator is IdentityGenerator; identitySelectString = useIdentityColumn ? dialect.IdentitySelectString : null; // UNSAVED-VALUE: unsavedIdentifierValue = UnsavedValueFactory.GetUnsavedIdentifierValue( model.Identifier.NullValue, identifierGetter, identifierType, constructor ); // VERSION: if( model.IsVersioned ) { foreach( Column col in model.Version.ColumnCollection ) { versionColumnName = col.GetQuotedName( Dialect ); break; //only happens once } } else { versionColumnName = null; } if( model.IsVersioned ) { //versionPropertyName = model.Version.Name; versioned = true; versionGetter = model.Version.GetGetter( mappedClass ); versionType = ( IVersionType ) model.Version.Type; } else { //versionPropertyName = null; versioned = false; versionGetter = null; versionType = null; } // VERSION UNSAVED-VALUE: unsavedVersionValue = model.IsVersioned ? UnsavedValueFactory.GetUnsavedVersionValue( model.Version.NullValue, versionGetter, versionType, constructor ) : Cascades.VersionValue.VersionUndefined; // PROPERTIES propertyTypes = new IType[hydrateSpan]; propertyNames = new string[hydrateSpan]; propertyUpdateability = new bool[hydrateSpan]; propertyInsertability = new bool[hydrateSpan]; propertyNullability = new bool[hydrateSpan]; getters = new IGetter[hydrateSpan]; setters = new ISetter[hydrateSpan]; cascadeStyles = new Cascades.CascadeStyle[hydrateSpan]; string[ ] setterNames = new string[hydrateSpan]; string[ ] getterNames = new string[hydrateSpan]; System.Type[ ] types = new System.Type[hydrateSpan]; i = 0; int tempVersionProperty = -66; bool foundCascade = false; bool foundCustomAccessor = false; foreach( Mapping.Property prop in model.PropertyClosureCollection ) { if( prop == model.Version ) { tempVersionProperty = i; } propertyNames[ i ] = prop.Name; if( !prop.IsBasicPropertyAccessor ) { foundCustomAccessor = true; } getters[ i ] = prop.GetGetter( mappedClass ); setters[ i ] = prop.GetSetter( mappedClass ); getterNames[ i ] = getters[ i ].PropertyName; setterNames[ i ] = setters[ i ].PropertyName; types[ i ] = getters[ i ].ReturnType; propertyTypes[ i ] = prop.Type; propertyUpdateability[ i ] = prop.IsUpdateable; propertyInsertability[ i ] = prop.IsInsertable; propertyNullability[ i ] = prop.IsNullable; gettersByPropertyName[ propertyNames[ i ] ] = getters[ i ]; settersByPropertyName[ propertyNames[ i ] ] = setters[ i ]; typesByPropertyName[ propertyNames[ i ] ] = propertyTypes[ i ]; cascadeStyles[ i ] = prop.CascadeStyle; if( cascadeStyles[ i ] != Cascades.CascadeStyle.StyleNone ) { foundCascade = true; } i++; } // NH: reflection optimizer works with custom accessors if( /*!foundCustomAccessor &&*/ Cfg.Environment.UseReflectionOptimizer ) { getset = GetSetHelperFactory.Create( MappedClass, Setters, Getters ); } hasCascades = foundCascade; versionProperty = tempVersionProperty; // CALLBACK INTERFACES implementsLifecycle = typeof( ILifecycle ).IsAssignableFrom( mappedClass ); implementsValidatable = typeof( IValidatable ).IsAssignableFrom( mappedClass ); cache = model.Cache; hasCollections = InitHasCollections(); // PROXIES concreteProxyClass = model.ProxyInterface; hasProxy = concreteProxyClass != null; if( hasProxy ) { HashedSet proxyInterfaces = new HashedSet(); proxyInterfaces.Add( typeof( INHibernateProxy ) ); if( !mappedClass.Equals( concreteProxyClass ) ) { if( !concreteProxyClass.IsInterface ) { throw new MappingException( "proxy must be either an interface, or the class itself: " + mappedClass.FullName ); } proxyInterfaces.Add( concreteProxyClass ); } if( mappedClass.IsInterface ) { proxyInterfaces.Add( mappedClass ); } if( hasProxy ) { foreach( Subclass subclass in model.SubclassCollection ) { System.Type subclassProxy = subclass.ProxyInterface; if( subclassProxy == null ) { throw new MappingException( "All subclasses must also have proxies: " + mappedClass.Name ); } if( !subclass.MappedClass.Equals( subclassProxy ) ) { proxyInterfaces.Add( subclassProxy ); } } } if( hasProxy ) { proxyFactory = CreateProxyFactory(); proxyFactory.PostInstantiate( mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod ); } else { proxyFactory = null; } } else { proxyFactory = null; } }
/// <summary> /// Set up a cache for a collection role /// </summary> public Configuration SetCacheConcurrencyStrategy( string collectionRole, ICacheConcurrencyStrategy concurrencyStrategy ) { SetCacheConcurrencyStrategy( collectionRole, concurrencyStrategy, collectionRole ); return this; }
/// <summary> /// Set up a cache for an entity class /// </summary> public Configuration SetCacheConcurrencyStrategy( System.Type clazz, ICacheConcurrencyStrategy concurrencyStrategy ) { SetCacheConcurrencyStrategy( clazz, concurrencyStrategy, clazz.FullName ); return this; }
//INITIALIZATION: public SingleTableEntityPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(model, cache, factory) { // CLASS + TABLE System.Type mappedClass = model.MappedClass; Table table = model.RootTable; qualifiedTableName = table.GetQualifiedName(Dialect, factory.DefaultSchema); tableNames = new string[] {qualifiedTableName}; // Custom sql customSQLInsert = new SqlString[1]; customSQLUpdate = new SqlString[1]; customSQLDelete = new SqlString[1]; insertCallable = new bool[1]; updateCallable = new bool[1]; deleteCallable = new bool[1]; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; customSQLInsert[0] = model.CustomSQLInsert; insertCallable[0] = customSQLInsert[0] != null && model.IsCustomInsertCallable; insertResultCheckStyles[0] = model.CustomSQLInsertCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]) : model.CustomSQLInsertCheckStyle; customSQLUpdate[0] = model.CustomSQLUpdate; updateCallable[0] = customSQLUpdate[0] != null && model.IsCustomUpdateCallable; updateResultCheckStyles[0] = model.CustomSQLUpdateCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]) : model.CustomSQLUpdateCheckStyle; customSQLDelete[0] = model.CustomSQLDelete; deleteCallable[0] = customSQLDelete[0] != null && model.IsCustomDeleteCallable; deleteResultCheckStyles[0] = model.CustomSQLDeleteCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]) : model.CustomSQLDeleteCheckStyle; // detect mapping errors HashedSet distinctColumns = new HashedSet(); // DISCRIMINATOR if (model.IsPolymorphic) { IValue d = model.Discriminator; if (d == null) { throw new MappingException("A discriminator mapping required for polymorphic persistence of " + model.Name); } forceDiscriminator = model.IsForceDiscriminator; // the discriminator will have only one column foreach (ISelectable selectable in d.ColumnCollection) { if (d.HasFormula) { Formula formula = (Formula) selectable; discriminatorFormula = formula.FormulaString; discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); discriminatorColumnName = null; discriminatorAlias = "clazz_"; } else { Column column = (Column) selectable; discriminatorColumnName = column.GetQuotedName(Dialect); discriminatorAlias = column.GetAlias(Dialect); discriminatorFormula = null; discriminatorFormulaTemplate = null; } } discriminatorType = model.Discriminator.Type; if (model.IsDiscriminatorValueNull) { discriminatorValue = NullDiscriminator; discriminatorSQLValue = InFragment.Null; discriminatorInsertable = false; } else if (model.IsDiscriminatorValueNotNull) { discriminatorValue = NotNullDiscriminator; discriminatorSQLValue = InFragment.NotNull; discriminatorInsertable = false; } else { discriminatorInsertable = model.IsDiscriminatorInsertable && !d.HasFormula; try { IDiscriminatorType dtype = (IDiscriminatorType) discriminatorType; discriminatorValue = dtype.StringToObject(model.DiscriminatorValue); discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue); } catch (InvalidCastException) { throw new MappingException(string.Format("Illegal discriminator type: {0}", discriminatorType.Name)); } catch (Exception e) { string msg = String.Format("Could not format discriminator value '{0}' to sql string using the IType {1}", model.DiscriminatorValue, model.Discriminator.Type.ToString()); throw new MappingException(msg, e); } if (discriminatorInsertable) { distinctColumns.Add(discriminatorColumnName); } } } else { forceDiscriminator = false; discriminatorInsertable = false; discriminatorColumnName = null; discriminatorAlias = null; discriminatorType = null; discriminatorValue = null; discriminatorSQLValue = null; } // PROPERTIES HashedSet thisClassProperties = new HashedSet(); foreach (Mapping.Property prop in model.PropertyClosureCollection) { thisClassProperties.Add(prop); } // SQL string generation moved to PostInstantiate int subclassSpan = model.SubclassSpan + 1; subclassClosure = new System.Type[subclassSpan]; subclassClosure[0] = mappedClass; if (model.IsPolymorphic) { subclassesByDiscriminatorValue.Add(discriminatorValue, mappedClass); } // SUBCLASSES if (model.IsPolymorphic) { int k = 1; foreach (Subclass sc in model.SubclassCollection) { subclassClosure[k++] = sc.MappedClass; if (sc.IsDiscriminatorValueNull) { subclassesByDiscriminatorValue.Add(NullDiscriminator, sc.MappedClass); } else if (sc.IsDiscriminatorValueNotNull) { subclassesByDiscriminatorValue.Add(NotNullDiscriminator, sc.MappedClass); } else { try { IDiscriminatorType dtype = discriminatorType as IDiscriminatorType; subclassesByDiscriminatorValue.Add( dtype.StringToObject(sc.DiscriminatorValue), sc.MappedClass); } catch (InvalidCastException) { throw new MappingException(string.Format("Illegal discriminator type: {0}", discriminatorType.Name)); } catch (Exception e) { throw new MappingException(string.Format("Error parsing discriminator value: '{0}'", sc.DiscriminatorValue), e); } } } } // This is in PostInstatiate as it needs identifier info //InitLockers(); propertyTableNumbers = new int[EntityMetamodel.PropertySpan]; for (int i = 0; i < propertyTableNumbers.Length; i++) { propertyTableNumbers[i] = 0; } InitSubclassPropertyAliasesMap(model); PostConstruct(mapping); }
public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, Configuration cfg) { ConstructorInfo pc; var use4Parameters = false; try { pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs); if (pc == null) { use4Parameters = true; pc = persisterClass.GetConstructor(CollectionPersisterConstructor2Args); } } catch (Exception e) { throw new MappingException("Could not get constructor for " + persisterClass.Name, e); } if(pc == null) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Could not find a public constructor for " + persisterClass.Name +";"); messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructorArgs.Length + " parameters of types (in order):"); System.Array.ForEach(CollectionPersisterConstructorArgs, t=> messageBuilder.AppendLine(t.FullName)); messageBuilder.AppendLine(); messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructor2Args.Length + " parameters of types (in order):"); System.Array.ForEach(CollectionPersisterConstructor2Args, t => messageBuilder.AppendLine(t.FullName)); throw new MappingException(messageBuilder.ToString()); } try { if (!use4Parameters) { return (ICollectionPersister) pc.Invoke(new object[] {model, cache, factory}); } return (ICollectionPersister)pc.Invoke(new object[] { model, cache, cfg, factory }); } catch (TargetInvocationException tie) { Exception e = tie.InnerException; if (e is HibernateException) { throw e; } else { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } } catch (Exception e) { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } }
public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) { this.factory = factory; this.cache = cache; if (factory.Settings.IsStructuredCacheEntriesEnabled) { cacheEntryStructure = collection.IsMap ? (ICacheEntryStructure) new StructuredMapCacheEntry() : (ICacheEntryStructure) new StructuredCollectionCacheEntry(); } else { cacheEntryStructure = new UnstructuredCacheEntry(); } dialect = factory.Dialect; sqlExceptionConverter = factory.SQLExceptionConverter; collectionType = collection.CollectionType; role = collection.Role; entityName = collection.OwnerEntityName; ownerPersister = factory.GetEntityPersister(entityName); queryLoaderName = collection.LoaderName; nodeName = collection.NodeName; isMutable = collection.IsMutable; Table table = collection.CollectionTable; fetchMode = collection.Element.FetchMode; elementType = collection.Element.Type; isPrimitiveArray = collection.IsPrimitiveArray; isArray = collection.IsArray; subselectLoadable = collection.IsSubselectLoadable; qualifiedTableName = table.GetQualifiedName(dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); int spacesSize = 1 + collection.SynchronizedTables.Count; spaces = new string[spacesSize]; int ispa = 0; spaces[ispa++] = qualifiedTableName; foreach (string s in collection.SynchronizedTables) { spaces[ispa++] = s; } sqlOrderByString = collection.OrderBy; hasOrder = sqlOrderByString != null; sqlOrderByStringTemplate = hasOrder ? Template.RenderOrderByStringTemplate(sqlOrderByString, dialect, factory.SQLFunctionRegistry) : null; sqlWhereString = !string.IsNullOrEmpty(collection.Where) ? '(' + collection.Where + ')' : null; hasWhere = sqlWhereString != null; sqlWhereStringTemplate = hasWhere ? Template.RenderWhereStringTemplate(sqlWhereString, dialect, factory.SQLFunctionRegistry) : null; hasOrphanDelete = collection.HasOrphanDelete; int batch = collection.BatchSize; if (batch == -1) { batch = factory.Settings.DefaultBatchFetchSize; } batchSize = batch; isVersioned = collection.IsOptimisticLocked; keyType = collection.Key.Type; int keySpan = collection.Key.ColumnSpan; keyColumnNames = new string[keySpan]; keyColumnAliases = new string[keySpan]; int k = 0; foreach (Column col in collection.Key.ColumnIterator) { keyColumnNames[k] = col.GetQuotedName(dialect); keyColumnAliases[k] = col.GetAlias(dialect); k++; } ISet distinctColumns = new HashedSet(); CheckColumnDuplication(distinctColumns, collection.Key.ColumnIterator); #region Element IValue element = collection.Element; if (!collection.IsOneToMany) { CheckColumnDuplication(distinctColumns, element.ColumnIterator); } string elemNode = collection.ElementNodeName; if (elementType.IsEntityType) { string _entityName = ((EntityType) elementType).GetAssociatedEntityName(); elementPersister = factory.GetEntityPersister(_entityName); if (elemNode == null) { elemNode = cfg.GetClassMapping(_entityName).NodeName; } // NativeSQL: collect element column and auto-aliases } else { elementPersister = null; } elementNodeName = elemNode; int elementSpan = element.ColumnSpan; elementColumnAliases = new string[elementSpan]; elementColumnNames = new string[elementSpan]; elementFormulaTemplates = new string[elementSpan]; elementFormulas = new string[elementSpan]; elementColumnIsSettable = new bool[elementSpan]; elementColumnIsInPrimaryKey = new bool[elementSpan]; bool isPureFormula = true; bool hasNotNullableColumns = false; int j = 0; foreach (ISelectable selectable in element.ColumnIterator) { elementColumnAliases[j] = selectable.GetAlias(dialect); if (selectable.IsFormula) { Formula form = (Formula) selectable; elementFormulaTemplates[j] = form.GetTemplate(dialect, factory.SQLFunctionRegistry); elementFormulas[j] = form.FormulaString; } else { Column col = (Column) selectable; elementColumnNames[j] = col.GetQuotedName(dialect); elementColumnIsSettable[j] = true; elementColumnIsInPrimaryKey[j] = !col.IsNullable; if (!col.IsNullable) { hasNotNullableColumns = true; } isPureFormula = false; } j++; } elementIsPureFormula = isPureFormula; //workaround, for backward compatibility of sets with no //not-null columns, assume all columns are used in the //row locator SQL if (!hasNotNullableColumns) { ArrayHelper.Fill(elementColumnIsInPrimaryKey, true); } #endregion #region INDEX AND ROW SELECT hasIndex = collection.IsIndexed; if (hasIndex) { // NativeSQL: collect index column and auto-aliases IndexedCollection indexedCollection = (IndexedCollection) collection; indexType = indexedCollection.Index.Type; int indexSpan = indexedCollection.Index.ColumnSpan; indexColumnNames = new string[indexSpan]; indexFormulaTemplates = new string[indexSpan]; indexFormulas = new string[indexSpan]; indexColumnIsSettable = new bool[indexSpan]; indexColumnAliases = new string[indexSpan]; bool hasFormula = false; int i = 0; foreach (ISelectable selectable in indexedCollection.Index.ColumnIterator) { indexColumnAliases[i] = selectable.GetAlias(dialect); if (selectable.IsFormula) { Formula indexForm = (Formula) selectable; indexFormulaTemplates[i] = indexForm.GetTemplate(dialect, factory.SQLFunctionRegistry); indexFormulas[i] = indexForm.FormulaString; hasFormula = true; } else { Column indexCol = (Column) selectable; indexColumnNames[i] = indexCol.GetQuotedName(dialect); indexColumnIsSettable[i] = true; } i++; } indexContainsFormula = hasFormula; baseIndex = indexedCollection.IsList ? ((List) indexedCollection).BaseIndex : 0; indexNodeName = indexedCollection.IndexNodeName; CheckColumnDuplication(distinctColumns, indexedCollection.Index.ColumnIterator); } else { indexContainsFormula = false; indexColumnIsSettable = null; indexFormulaTemplates = null; indexFormulas = null; indexType = null; indexColumnNames = null; indexColumnAliases = null; baseIndex = 0; indexNodeName = null; } hasIdentifier = collection.IsIdentified; if (hasIdentifier) { if (collection.IsOneToMany) { throw new MappingException("one-to-many collections with identifiers are not supported."); } IdentifierCollection idColl = (IdentifierCollection) collection; identifierType = idColl.Identifier.Type; Column col = null; foreach (Column column in idColl.Identifier.ColumnIterator) { col = column; break; } identifierColumnName = col.GetQuotedName(dialect); identifierColumnAlias = col.GetAlias(dialect); identifierGenerator = idColl.Identifier.CreateIdentifierGenerator(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName, null); // NH see : identityDelegate declaration IPostInsertIdentifierGenerator pig = (identifierGenerator as IPostInsertIdentifierGenerator); if (pig != null) { identityDelegate = pig.GetInsertGeneratedIdentifierDelegate(this, Factory, UseGetGeneratedKeys()); } else { identityDelegate = null; } CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnIterator); } else { identifierType = null; identifierColumnName = null; identifierColumnAlias = null; identifierGenerator = null; identityDelegate = null; } #endregion #region GENERATE THE SQL // NH Different behavior : for the Insert SQL we are managing isPostInsertIdentifier (not supported in H3.2.5) if (collection.CustomSQLInsert == null) { if (!IsIdentifierAssignedByInsert) { sqlInsertRowString = GenerateInsertRowString(); } else { sqlInsertRowString = GenerateIdentityInsertRowString(); } insertCallable = false; insertCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { SqlType[] parmsTypes = GenerateInsertRowString().ParameterTypes; sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, parmsTypes); insertCallable = collection.IsCustomInsertCallable; insertCheckStyle = collection.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable); } sqlUpdateRowString = GenerateUpdateRowString(); if (collection.CustomSQLUpdate == null) { updateCallable = false; updateCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { sqlUpdateRowString = new SqlCommandInfo(collection.CustomSQLUpdate, sqlUpdateRowString.ParameterTypes); updateCallable = collection.IsCustomUpdateCallable; updateCheckStyle = collection.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable); } sqlDeleteRowString = GenerateDeleteRowString(); if (collection.CustomSQLDelete == null) { deleteCallable = false; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteRowString = new SqlCommandInfo(collection.CustomSQLDelete, sqlDeleteRowString.ParameterTypes); deleteCallable = collection.IsCustomDeleteCallable; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } sqlDeleteString = GenerateDeleteString(); if (collection.CustomSQLDeleteAll == null) { deleteAllCallable = false; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteString = new SqlCommandInfo(collection.CustomSQLDeleteAll, sqlDeleteString.ParameterTypes); deleteAllCallable = collection.IsCustomDeleteAllCallable; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } isCollectionIntegerIndex = collection.IsIndexed && !collection.IsMap; sqlDetectRowByIndexString = GenerateDetectRowByIndexString(); sqlDetectRowByElementString = GenerateDetectRowByElementString(); sqlSelectRowByIndexString = GenerateSelectRowByIndexString(); LogStaticSQL(); #endregion isLazy = collection.IsLazy; isExtraLazy = collection.ExtraLazy; isInverse = collection.IsInverse; if (collection.IsArray) { elementClass = ((Array) collection).ElementClass; } else { // for non-arrays, we don't need to know the element class elementClass = null; } if (elementType.IsComponentType) { elementPropertyMapping = new CompositeElementPropertyMapping(elementColumnNames, elementFormulaTemplates, (IAbstractComponentType) elementType, factory); } else if (!elementType.IsEntityType) { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } else { elementPropertyMapping = elementPersister as IPropertyMapping; if (elementPropertyMapping == null) { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } } // Handle any filters applied to this collection filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry); // Handle any filters applied to this collection for many-to-many manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry); manyToManyWhereString = !string.IsNullOrEmpty(collection.ManyToManyWhere) ? "( " + collection.ManyToManyWhere + " )" : null; manyToManyWhereTemplate = manyToManyWhereString == null ? null : Template.RenderWhereStringTemplate(manyToManyWhereString, factory.Dialect, factory.SQLFunctionRegistry); manyToManyOrderByString = collection.ManyToManyOrdering; manyToManyOrderByTemplate = manyToManyOrderByString == null ? null : Template.RenderOrderByStringTemplate(manyToManyOrderByString, factory.Dialect, factory.SQLFunctionRegistry); InitCollectionPropertyMap(); }
protected AbstractEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { this.factory = factory; dialect = factory.Dialect; this.cache = cache; //sqlExceptionConverter = factory.SQLExceptionConverter; entityMetamodel = new EntityMetamodel(persistentClass, factory); // CLASS mappedClass = persistentClass.MappedClass; sqlWhereString = persistentClass.Where; sqlWhereStringTemplate = sqlWhereString == null ? null : Template.RenderWhereStringTemplate(sqlWhereString, Dialect, factory.SQLFunctionRegistry); batchSize = persistentClass.BatchSize; hasSubselectLoadableCollections = persistentClass.HasSubselectLoadableCollections; constructor = ReflectHelper.GetDefaultConstructor(mappedClass); // verify that the class has a default constructor if it is not abstract - it is considered // a mapping exception if the default ctor is missing. if (!entityMetamodel.IsAbstract && constructor == null) { throw new MappingException("The mapped class " + mappedClass.FullName + " must declare a default (no-arg) constructor."); } // IDENTIFIER hasEmbeddedIdentifier = persistentClass.HasEmbeddedIdentifier; IValue idValue = persistentClass.Identifier; if (persistentClass.HasIdentifierProperty) { Mapping.Property idProperty = persistentClass.IdentifierProperty; identifierSetter = idProperty.GetSetter(mappedClass); identifierGetter = idProperty.GetGetter(mappedClass); } else { identifierGetter = null; identifierSetter = null; } System.Type prox = persistentClass.ProxyInterface; MethodInfo proxySetIdentifierMethod = null; MethodInfo proxyGetIdentifierMethod = null; if (persistentClass.HasIdentifierProperty && prox != null) { Mapping.Property idProperty = persistentClass.IdentifierProperty; proxyGetIdentifierMethod = idProperty.GetGetter(prox).Method; proxySetIdentifierMethod = idProperty.GetSetter(prox).Method; } // HYDRATE SPAN hydrateSpan = persistentClass.PropertyClosureCollection.Count; // IDENTIFIER identifierColumnSpan = persistentClass.Identifier.ColumnSpan; rootTableKeyColumnNames = new string[identifierColumnSpan]; identifierAliases = new string[identifierColumnSpan]; loaderName = persistentClass.LoaderName; int i = 0; foreach (Column col in idValue.ColumnCollection) { rootTableKeyColumnNames[i] = col.GetQuotedName(factory.Dialect); identifierAliases[i] = col.GetAlias(Dialect, persistentClass.RootTable); i++; } // VERSION: if (persistentClass.IsVersioned) { foreach (Column col in persistentClass.Version.ColumnCollection) { versionColumnName = col.GetQuotedName(Dialect); break; //only happens once } } else { versionColumnName = null; } if (persistentClass.IsVersioned) { versionGetter = persistentClass.Version.GetGetter(mappedClass); versionType = (IVersionType) persistentClass.Version.Type; } else { versionGetter = null; versionType = null; } // PROPERTIES getters = new IGetter[hydrateSpan]; setters = new ISetter[hydrateSpan]; string[] setterNames = new string[hydrateSpan]; string[] getterNames = new string[hydrateSpan]; System.Type[] classes = new System.Type[hydrateSpan]; i = 0; // NH: reflection optimizer works with custom accessors //bool foundCustomAccessor = false; foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection) { //if( !prop.IsBasicPropertyAccessor ) //{ // foundCustomAccessor = true; //} getters[i] = prop.GetGetter(mappedClass); setters[i] = prop.GetSetter(mappedClass); getterNames[i] = getters[i].PropertyName; setterNames[i] = setters[i].PropertyName; classes[i] = getters[i].ReturnType; string propertyName = prop.Name; gettersByPropertyName[propertyName] = getters[i]; settersByPropertyName[propertyName] = setters[i]; i++; } // PROPERTIES (FROM ABSTRACTENTITYPERSISTER SUBCLASSES) propertyColumnNames = new string[HydrateSpan][]; propertyColumnAliases = new string[HydrateSpan][]; propertyColumnSpans = new int[HydrateSpan]; propertyColumnFormulaTemplates = new string[HydrateSpan][]; propertyColumnUpdateable = new bool[HydrateSpan][]; propertyColumnInsertable = new bool[HydrateSpan][]; propertyUniqueness = new bool[HydrateSpan]; HashedSet thisClassProperties = new HashedSet(); i = 0; bool foundFormula = false; foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection) { thisClassProperties.Add(prop); int span = prop.ColumnSpan; propertyColumnSpans[i] = span; string[] colNames = new string[span]; string[] colAliases = new string[span]; string[] templates = new string[span]; int k = 0; foreach (ISelectable thing in prop.ColumnCollection) { colAliases[k] = thing.GetAlias(factory.Dialect, prop.Value.Table); if (thing.IsFormula) { foundFormula = true; templates[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); } else { colNames[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); } k++; } propertyColumnNames[i] = colNames; propertyColumnFormulaTemplates[i] = templates; propertyColumnAliases[i] = colAliases; propertyColumnInsertable[i] = prop.Value.ColumnInsertability; propertyColumnUpdateable[i] = prop.Value.ColumnUpdateability; propertyUniqueness[i] = prop.Value.IsUnique; i++; } hasFormulaProperties = foundFormula; // NH: reflection optimizer works with custom accessors if (Environment.UseReflectionOptimizer) { optimizer = Environment.BytecodeProvider.GetReflectionOptimizer(MappedClass, Getters, Setters); } // SUBCLASS PROPERTY CLOSURE ArrayList columns = new ArrayList(); //this.subclassColumnClosure ArrayList aliases = new ArrayList(); ArrayList formulaAliases = new ArrayList(); ArrayList formulaTemplates = new ArrayList(); ArrayList types = new ArrayList(); //this.subclassPropertyTypeClosure ArrayList names = new ArrayList(); //this.subclassPropertyNameClosure ArrayList subclassTemplates = new ArrayList(); ArrayList propColumns = new ArrayList(); //this.subclassPropertyColumnNameClosure ArrayList joinedFetchesList = new ArrayList(); //this.subclassPropertyEnableJoinedFetch ArrayList cascades = new ArrayList(); ArrayList definedBySubclass = new ArrayList(); // this.propertyDefinedOnSubclass ArrayList formulas = new ArrayList(); ArrayList propNullables = new ArrayList(); foreach (Mapping.Property prop in persistentClass.SubclassPropertyClosureCollection) { names.Add(prop.Name); bool isDefinedBySubclass = !thisClassProperties.Contains(prop); definedBySubclass.Add(isDefinedBySubclass); propNullables.Add(prop.IsOptional || isDefinedBySubclass); //TODO: is this completely correct? types.Add(prop.Type); string[] cols = new string[prop.ColumnSpan]; string[] forms = new string[prop.ColumnSpan]; int[] colnos = new int[prop.ColumnSpan]; int[] formnos = new int[prop.ColumnSpan]; int l = 0; foreach (ISelectable thing in prop.ColumnCollection) { if (thing.IsFormula) { string template = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); formnos[l] = formulaTemplates.Count; colnos[l] = -1; formulaTemplates.Add(template); forms[l] = template; formulas.Add(thing.GetText(factory.Dialect)); formulaAliases.Add(thing.GetAlias(factory.Dialect)); // TODO H3: formulasLazy.add( lazy ); } else { String colName = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); colnos[l] = columns.Count; //before add :-) formnos[l] = -1; columns.Add(colName); cols[l] = colName; aliases.Add(thing.GetAlias(factory.Dialect, prop.Value.Table)); // TODO H3: columnsLazy.add( lazy ); // TODO H3: columnSelectables.add( new Boolean( prop.isSelectable() ) ); } l++; } propColumns.Add(cols); subclassTemplates.Add(forms); //propColumnNumbers.Add( colnos ); //propFormulaNumbers.Add( formnos ); joinedFetchesList.Add(prop.Value.FetchMode); cascades.Add(prop.CascadeStyle); } subclassColumnClosure = (string[]) columns.ToArray(typeof(string)); subclassFormulaClosure = (string[]) formulas.ToArray(typeof(string)); subclassFormulaTemplateClosure = (string[]) formulaTemplates.ToArray(typeof(string)); subclassPropertyTypeClosure = (IType[]) types.ToArray(typeof(IType)); subclassColumnAliasClosure = (string[]) aliases.ToArray(typeof(string)); subclassFormulaAliasClosure = (string[]) formulaAliases.ToArray(typeof(string)); subclassPropertyNameClosure = (string[]) names.ToArray(typeof(string)); subclassPropertyNullabilityClosure = (bool[]) propNullables.ToArray(typeof(bool)); subclassPropertyFormulaTemplateClosure = ArrayHelper.To2DStringArray(subclassTemplates); subclassPropertyColumnNameClosure = (string[][]) propColumns.ToArray(typeof(string[])); subclassPropertyCascadeStyleClosure = new Cascades.CascadeStyle[cascades.Count]; int m = 0; foreach (Cascades.CascadeStyle cs in cascades) { subclassPropertyCascadeStyleClosure[m++] = cs; } subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.Count]; m = 0; foreach (FetchMode qq in joinedFetchesList) { subclassPropertyFetchModeClosure[m++] = qq; } propertyDefinedOnSubclass = new bool[definedBySubclass.Count]; m = 0; foreach (bool val in definedBySubclass) { propertyDefinedOnSubclass[m++] = val; } // CALLBACK INTERFACES implementsLifecycle = typeof(ILifecycle).IsAssignableFrom(mappedClass); implementsValidatable = typeof(IValidatable).IsAssignableFrom(mappedClass); // PROXIES concreteProxyClass = persistentClass.ProxyInterface; bool hasProxy = concreteProxyClass != null; if (hasProxy) { HashedSet proxyInterfaces = new HashedSet(); proxyInterfaces.Add(typeof(INHibernateProxy)); if (!mappedClass.Equals(concreteProxyClass)) { if (!concreteProxyClass.IsInterface) { throw new MappingException( "proxy must be either an interface, or the class itself: " + mappedClass.FullName); } proxyInterfaces.Add(concreteProxyClass); } if (mappedClass.IsInterface) { proxyInterfaces.Add(mappedClass); } if (HasProxy) { foreach (Subclass subclass in persistentClass.SubclassCollection) { System.Type subclassProxy = subclass.ProxyInterface; if (subclassProxy == null) { throw new MappingException("All subclasses must also have proxies: " + mappedClass.Name); } if (!subclass.MappedClass.Equals(subclassProxy)) { proxyInterfaces.Add(subclassProxy); } } } if (HasProxy) { proxyFactory = CreateProxyFactory(); proxyFactory.PostInstantiate(mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod); } else { proxyFactory = null; } } else { proxyFactory = null; } // Handle any filters applied to the class level filterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry); }
public SingleTableEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory) { #region CLASS + TABLE joinSpan = persistentClass.JoinClosureSpan + 1; qualifiedTableNames = new string[joinSpan]; isInverseTable = new bool[joinSpan]; isNullableTable = new bool[joinSpan]; keyColumnNames = new string[joinSpan][]; Table table = persistentClass.RootTable; qualifiedTableNames[0] = table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); isInverseTable[0] = false; isNullableTable[0] = false; keyColumnNames[0] = IdentifierColumnNames; cascadeDeleteEnabled = new bool[joinSpan]; // Custom sql customSQLInsert = new SqlString[joinSpan]; customSQLUpdate = new SqlString[joinSpan]; customSQLDelete = new SqlString[joinSpan]; insertCallable = new bool[joinSpan]; updateCallable = new bool[joinSpan]; deleteCallable = new bool[joinSpan]; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; customSQLInsert[0] = persistentClass.CustomSQLInsert; insertCallable[0] = customSQLInsert[0] != null && persistentClass.IsCustomInsertCallable; insertResultCheckStyles[0] = persistentClass.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]); customSQLUpdate[0] = persistentClass.CustomSQLUpdate; updateCallable[0] = customSQLUpdate[0] != null && persistentClass.IsCustomUpdateCallable; updateResultCheckStyles[0] = persistentClass.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]); customSQLDelete[0] = persistentClass.CustomSQLDelete; deleteCallable[0] = customSQLDelete[0] != null && persistentClass.IsCustomDeleteCallable; deleteResultCheckStyles[0] = persistentClass.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]); #endregion #region JOINS int j = 1; foreach (Join join in persistentClass.JoinClosureIterator) { qualifiedTableNames[j] = join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); isInverseTable[j] = join.IsInverse; isNullableTable[j] = join.IsOptional; cascadeDeleteEnabled[j] = join.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete; customSQLInsert[j] = join.CustomSQLInsert; insertCallable[j] = customSQLInsert[j] != null && join.IsCustomInsertCallable; insertResultCheckStyles[j] = join.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[j], insertCallable[j]); customSQLUpdate[j] = join.CustomSQLUpdate; updateCallable[j] = customSQLUpdate[j] != null && join.IsCustomUpdateCallable; updateResultCheckStyles[j] = join.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[j], updateCallable[j]); customSQLDelete[j] = join.CustomSQLDelete; deleteCallable[j] = customSQLDelete[j] != null && join.IsCustomDeleteCallable; deleteResultCheckStyles[j] = join.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[j], deleteCallable[j]); IEnumerable<Column> enumerableKeyCol = new SafetyEnumerable<Column>(join.Key.ColumnIterator); List<string> kcName = new List<string>(join.Key.ColumnSpan); foreach (Column col in enumerableKeyCol) kcName.Add(col.GetQuotedName(factory.Dialect)); keyColumnNames[j] = kcName.ToArray(); j++; } constraintOrderedTableNames = new string[qualifiedTableNames.Length]; constraintOrderedKeyColumnNames = new string[qualifiedTableNames.Length][]; for (int i = qualifiedTableNames.Length - 1, position = 0; i >= 0; i--, position++) { constraintOrderedTableNames[position] = qualifiedTableNames[i]; constraintOrderedKeyColumnNames[position] = keyColumnNames[i]; } spaces = ArrayHelper.Join(qualifiedTableNames, ArrayHelper.ToStringArray(persistentClass.SynchronizedTables)); bool lazyAvailable = IsInstrumented(EntityMode.Poco); bool hasDeferred = false; List<string> subclassTables = new List<string>(); List<string[]> joinKeyColumns = new List<string[]>(); List<bool> isConcretes = new List<bool>(); List<bool> isDeferreds = new List<bool>(); List<bool> isInverses = new List<bool>(); List<bool> isNullables = new List<bool>(); List<bool> isLazies = new List<bool>(); subclassTables.Add(qualifiedTableNames[0]); joinKeyColumns.Add(IdentifierColumnNames); isConcretes.Add(true); isDeferreds.Add(false); isInverses.Add(false); isNullables.Add(false); isLazies.Add(false); foreach (Join join in persistentClass.SubclassJoinClosureIterator) { isConcretes.Add(persistentClass.IsClassOrSuperclassJoin(join)); isDeferreds.Add(join.IsSequentialSelect); isInverses.Add(join.IsInverse); isNullables.Add(join.IsOptional); isLazies.Add(lazyAvailable && join.IsLazy); if (join.IsSequentialSelect && !persistentClass.IsClassOrSuperclassJoin(join)) hasDeferred = true; subclassTables.Add(join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName)); IEnumerable<Column> enumerableKeyCol = new SafetyEnumerable<Column>(join.Key.ColumnIterator); List<string> keyCols = new List<string>(join.Key.ColumnSpan); foreach (Column col in enumerableKeyCol) keyCols.Add(col.GetQuotedName(factory.Dialect)); joinKeyColumns.Add(keyCols.ToArray()); } subclassTableSequentialSelect = isDeferreds.ToArray(); subclassTableNameClosure = subclassTables.ToArray(); subclassTableIsLazyClosure = isLazies.ToArray(); subclassTableKeyColumnClosure = joinKeyColumns.ToArray(); isClassOrSuperclassTable = isConcretes.ToArray(); isInverseSubclassTable = isInverses.ToArray(); isNullableSubclassTable = isNullables.ToArray(); hasSequentialSelects = hasDeferred; #endregion #region DISCRIMINATOR if (persistentClass.IsPolymorphic) { IValue discrimValue = persistentClass.Discriminator; if (discrimValue == null) throw new MappingException("Discriminator mapping required for single table polymorphic persistence"); forceDiscriminator = persistentClass.IsForceDiscriminator; IEnumerator<ISelectable> iSel = discrimValue.ColumnIterator.GetEnumerator(); iSel.MoveNext(); ISelectable selectable = iSel.Current; if (discrimValue.HasFormula) { Formula formula = (Formula)selectable; discriminatorFormula = formula.FormulaString; discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); discriminatorColumnName = null; discriminatorAlias = Discriminator_Alias; } else { Column column = (Column)selectable; discriminatorColumnName = column.GetQuotedName(factory.Dialect); discriminatorAlias = column.GetAlias(factory.Dialect, persistentClass.RootTable); discriminatorFormula = null; discriminatorFormulaTemplate = null; } discriminatorType = persistentClass.Discriminator.Type; if (persistentClass.IsDiscriminatorValueNull) { discriminatorValue = NullDiscriminator; discriminatorSQLValue = InFragment.Null; discriminatorInsertable = false; } else if (persistentClass.IsDiscriminatorValueNotNull) { discriminatorValue = NotNullDiscriminator; discriminatorSQLValue = InFragment.NotNull; discriminatorInsertable = false; } else { discriminatorInsertable = persistentClass.IsDiscriminatorInsertable && !discrimValue.HasFormula; try { IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType; discriminatorValue = dtype.StringToObject(persistentClass.DiscriminatorValue); discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue, factory.Dialect); } catch (InvalidCastException cce) { throw new MappingException( string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce); } catch (Exception e) { throw new MappingException("Could not format discriminator value to SQL string of entity " + persistentClass.EntityName, e); } } } else { forceDiscriminator = false; discriminatorInsertable = false; discriminatorColumnName = null; discriminatorAlias = null; discriminatorType = null; discriminatorValue = null; discriminatorSQLValue = null; discriminatorFormula = null; discriminatorFormulaTemplate = null; } #endregion #region PROPERTIES propertyTableNumbers = new int[PropertySpan]; int i2 = 0; foreach (Property prop in persistentClass.PropertyClosureIterator) { propertyTableNumbers[i2++] = persistentClass.GetJoinNumber(prop); } List<int> columnJoinNumbers = new List<int>(); List<int> formulaJoinedNumbers = new List<int>(); List<int> propertyJoinNumbers = new List<int>(); foreach (Property prop in persistentClass.SubclassPropertyClosureIterator) { int join = persistentClass.GetJoinNumber(prop); propertyJoinNumbers.Add(join); //propertyTableNumbersByName.put( prop.getName(), join ); propertyTableNumbersByNameAndSubclass[prop.PersistentClass.EntityName + '.' + prop.Name] = join; foreach (ISelectable thing in prop.ColumnIterator) { if (thing.IsFormula) formulaJoinedNumbers.Add(join); else columnJoinNumbers.Add(join); } } subclassColumnTableNumberClosure = columnJoinNumbers.ToArray(); subclassFormulaTableNumberClosure = formulaJoinedNumbers.ToArray(); subclassPropertyTableNumberClosure = propertyJoinNumbers.ToArray(); int subclassSpan = persistentClass.SubclassSpan + 1; subclassClosure = new string[subclassSpan]; subclassClosure[0] = EntityName; if (persistentClass.IsPolymorphic) subclassesByDiscriminatorValue[discriminatorValue] = EntityName; #endregion #region SUBCLASSES if (persistentClass.IsPolymorphic) { int k = 1; foreach (Subclass sc in persistentClass.SubclassIterator) { subclassClosure[k++] = sc.EntityName; if (sc.IsDiscriminatorValueNull) { subclassesByDiscriminatorValue[NullDiscriminator] = sc.EntityName; } else if (sc.IsDiscriminatorValueNotNull) { subclassesByDiscriminatorValue[NotNullDiscriminator] = sc.EntityName; } else { if (discriminatorType == null) throw new MappingException("Not available discriminator type of entity " + persistentClass.EntityName); try { IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType; subclassesByDiscriminatorValue[dtype.StringToObject(sc.DiscriminatorValue)] = sc.EntityName; } catch (InvalidCastException cce) { throw new MappingException( string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce); } catch (Exception e) { throw new MappingException("Error parsing discriminator value of entity " + persistentClass.EntityName, e); } } } } #endregion InitLockers(); InitSubclassPropertyAliasesMap(persistentClass); PostConstruct(mapping); }
public UnionSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory) { if (IdentifierGenerator is IdentityGenerator) { throw new MappingException("Cannot use identity column key generation with <union-subclass> mapping for: " + EntityName); } // TABLE var dialect = factory.Dialect; var defaultCatalogName = factory.Settings.DefaultCatalogName; var defaultSchemaName = factory.Settings.DefaultSchemaName; tableName = persistentClass.Table.GetQualifiedName(dialect, defaultCatalogName, defaultSchemaName); #region Custom SQL SqlString sql; bool callable; ExecuteUpdateResultCheckStyle checkStyle; sql = persistentClass.CustomSQLInsert; callable = sql != null && persistentClass.IsCustomInsertCallable; checkStyle = sql == null ? ExecuteUpdateResultCheckStyle.Count : (persistentClass.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable)); customSQLInsert = new SqlString[] { sql }; insertCallable = new bool[] { callable }; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; sql = persistentClass.CustomSQLUpdate; callable = sql != null && persistentClass.IsCustomUpdateCallable; checkStyle = sql == null ? ExecuteUpdateResultCheckStyle.Count : (persistentClass.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable)); customSQLUpdate = new SqlString[] { sql }; updateCallable = new bool[] { callable }; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; sql = persistentClass.CustomSQLDelete; callable = sql != null && persistentClass.IsCustomDeleteCallable; checkStyle = sql == null ? ExecuteUpdateResultCheckStyle.Count : (persistentClass.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(sql, callable)); customSQLDelete = new SqlString[] { sql }; deleteCallable = new bool[] { callable }; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; #endregion discriminatorValue = persistentClass.SubclassId; discriminatorSQLValue = persistentClass.SubclassId.ToString(); #region PROPERTIES int subclassSpan = persistentClass.SubclassSpan + 1; subclassClosure = new string[subclassSpan]; subclassClosure[0] = EntityName; #endregion #region SUBCLASSES subclassByDiscriminatorValue[persistentClass.SubclassId] = persistentClass.EntityName; if (persistentClass.IsPolymorphic) { int k = 1; foreach (Subclass sc in persistentClass.SubclassIterator) { subclassClosure[k++] = sc.EntityName; subclassByDiscriminatorValue[sc.SubclassId] = sc.EntityName; } } #endregion #region SPACES //TODO: i'm not sure, but perhaps we should exclude abstract denormalized tables? int spacesSize = 1 + persistentClass.SynchronizedTables.Count; spaces = new string[spacesSize]; spaces[0] = tableName; IEnumerator <string> iSyncTab = persistentClass.SynchronizedTables.GetEnumerator(); for (int i = 1; i < spacesSize; i++) { iSyncTab.MoveNext(); spaces[i] = iSyncTab.Current; } subclassSpaces = persistentClass.SubclassTableClosureIterator .Select(table => table.GetQualifiedName(dialect, defaultCatalogName, defaultSchemaName)) .Distinct().ToArray(); subquery = GenerateSubquery(persistentClass, mapping); if (IsMultiTable) { var tableNames = new List <string>(); var keyColumns = new List <string[]>(); if (!IsAbstract) { tableNames.Add(tableName); keyColumns.Add(IdentifierColumnNames); } foreach (var tab in persistentClass.SubclassTableClosureIterator) { if (!tab.IsAbstractUnionTable) { string _tableName = tab.GetQualifiedName(dialect, defaultCatalogName, defaultSchemaName); tableNames.Add(_tableName); var names = tab.PrimaryKey.ColumnIterator .Select(column => column.GetQuotedName(dialect)) .ToArray(); keyColumns.Add(names); } } constraintOrderedTableNames = tableNames.ToArray(); constraintOrderedKeyColumnNames = keyColumns.ToArray(); } else { constraintOrderedTableNames = new string[] { tableName }; constraintOrderedKeyColumnNames = new string[][] { IdentifierColumnNames }; } #endregion InitLockers(); InitSubclassPropertyAliasesMap(persistentClass); PostConstruct(mapping); }
protected AbstractEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { this.factory = factory; this.cache = cache; isLazyPropertiesCacheable = persistentClass.IsLazyPropertiesCacheable; cacheEntryStructure = factory.Settings.IsStructuredCacheEntriesEnabled ? (ICacheEntryStructure)new StructuredCacheEntry(this) : (ICacheEntryStructure)new UnstructuredCacheEntry(); entityMetamodel = new EntityMetamodel(persistentClass, factory); if (persistentClass.HasPocoRepresentation) { //TODO: this is currently specific to pojos, but need to be available for all entity-modes foreach (Subclass subclass in persistentClass.SubclassIterator) { entityNameBySubclass[subclass.MappedClass] = subclass.EntityName; } } batchSize = persistentClass.BatchSize.HasValue ? persistentClass.BatchSize.Value : factory.Settings.DefaultBatchFetchSize; hasSubselectLoadableCollections = persistentClass.HasSubselectLoadableCollections; propertyMapping = new BasicEntityPropertyMapping(this); #region IDENTIFIER identifierColumnSpan = persistentClass.Identifier.ColumnSpan; rootTableKeyColumnNames = new string[identifierColumnSpan]; identifierAliases = new string[identifierColumnSpan]; rowIdName = persistentClass.RootTable.RowId; loaderName = persistentClass.LoaderName; // TODO NH: Not safe cast to Column int i = 0; foreach (Column col in persistentClass.Identifier.ColumnIterator) { rootTableKeyColumnNames[i] = col.GetQuotedName(factory.Dialect); identifierAliases[i] = col.GetAlias(factory.Dialect, persistentClass.RootTable); i++; } #endregion #region VERSION if (persistentClass.IsVersioned) { foreach (Column col in persistentClass.Version.ColumnIterator) { versionColumnName = col.GetQuotedName(factory.Dialect); break; //only happens once } } else { versionColumnName = null; } #endregion #region WHERE STRING sqlWhereString = !string.IsNullOrEmpty(persistentClass.Where) ? "( " + persistentClass.Where + ") " : null; sqlWhereStringTemplate = sqlWhereString == null ? null : Template.RenderWhereStringTemplate(sqlWhereString, factory.Dialect, factory.SQLFunctionRegistry); #endregion #region PROPERTIES // NH: see consistence with the implementation on EntityMetamodel where we are disabling lazy-properties for no lazy entities bool lazyAvailable = IsInstrumented(EntityMode.Poco) && entityMetamodel.IsLazy; int hydrateSpan = entityMetamodel.PropertySpan; propertyColumnSpans = new int[hydrateSpan]; propertySubclassNames = new string[hydrateSpan]; propertyColumnAliases = new string[hydrateSpan][]; propertyColumnNames = new string[hydrateSpan][]; propertyColumnFormulaTemplates = new string[hydrateSpan][]; propertyUniqueness = new bool[hydrateSpan]; propertySelectable = new bool[hydrateSpan]; propertyColumnUpdateable = new bool[hydrateSpan][]; propertyColumnInsertable = new bool[hydrateSpan][]; var thisClassProperties = new HashSet<Property>(); lazyProperties = new HashedSet<string>(); List<string> lazyNames = new List<string>(); List<int> lazyNumbers = new List<int>(); List<IType> lazyTypes = new List<IType>(); List<string[]> lazyColAliases = new List<string[]>(); i = 0; bool foundFormula = false; foreach (Property prop in persistentClass.PropertyClosureIterator) { thisClassProperties.Add(prop); int span = prop.ColumnSpan; propertyColumnSpans[i] = span; propertySubclassNames[i] = prop.PersistentClass.EntityName; string[] colNames = new string[span]; string[] colAliases = new string[span]; string[] templates = new string[span]; int k = 0; foreach (ISelectable thing in prop.ColumnIterator) { colAliases[k] = thing.GetAlias(factory.Dialect, prop.Value.Table); if (thing.IsFormula) { foundFormula = true; templates[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); } else { colNames[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); } k++; } propertyColumnNames[i] = colNames; propertyColumnFormulaTemplates[i] = templates; propertyColumnAliases[i] = colAliases; if (lazyAvailable && prop.IsLazy) { lazyProperties.Add(prop.Name); lazyNames.Add(prop.Name); lazyNumbers.Add(i); lazyTypes.Add(prop.Value.Type); lazyColAliases.Add(colAliases); } propertyColumnUpdateable[i] = prop.Value.ColumnUpdateability; propertyColumnInsertable[i] = prop.Value.ColumnInsertability; propertySelectable[i] = prop.IsSelectable; propertyUniqueness[i] = prop.Value.IsAlternateUniqueKey; i++; } hasFormulaProperties = foundFormula; lazyPropertyColumnAliases = lazyColAliases.ToArray(); lazyPropertyNames = lazyNames.ToArray(); lazyPropertyNumbers = lazyNumbers.ToArray(); lazyPropertyTypes = lazyTypes.ToArray(); #endregion #region SUBCLASS PROPERTY CLOSURE List<string> columns = new List<string>(); List<bool> columnsLazy = new List<bool>(); List<string> aliases = new List<string>(); List<string> formulas = new List<string>(); List<string> formulaAliases = new List<string>(); List<string> formulaTemplates = new List<string>(); List<bool> formulasLazy = new List<bool>(); List<IType> types = new List<IType>(); List<string> names = new List<string>(); List<string> classes = new List<string>(); List<string[]> templates2 = new List<string[]>(); List<string[]> propColumns = new List<string[]>(); List<FetchMode> joinedFetchesList = new List<FetchMode>(); List<CascadeStyle> cascades = new List<CascadeStyle>(); List<bool> definedBySubclass = new List<bool>(); List<int[]> propColumnNumbers = new List<int[]>(); List<int[]> propFormulaNumbers = new List<int[]>(); List<bool> columnSelectables = new List<bool>(); List<bool> propNullables = new List<bool>(); foreach (Property prop in persistentClass.SubclassPropertyClosureIterator) { names.Add(prop.Name); classes.Add(prop.PersistentClass.EntityName); bool isDefinedBySubclass = !thisClassProperties.Contains(prop); definedBySubclass.Add(isDefinedBySubclass); propNullables.Add(prop.IsOptional || isDefinedBySubclass); //TODO: is this completely correct? types.Add(prop.Type); string[] cols = new string[prop.ColumnSpan]; string[] forms = new string[prop.ColumnSpan]; int[] colnos = new int[prop.ColumnSpan]; int[] formnos = new int[prop.ColumnSpan]; int l = 0; bool lazy = prop.IsLazy && lazyAvailable; foreach (ISelectable thing in prop.ColumnIterator) { if (thing.IsFormula) { string template = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); formnos[l] = formulaTemplates.Count; colnos[l] = -1; formulaTemplates.Add(template); forms[l] = template; formulas.Add(thing.GetText(factory.Dialect)); formulaAliases.Add(thing.GetAlias(factory.Dialect)); formulasLazy.Add(lazy); } else { string colName = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); colnos[l] = columns.Count; //before add :-) formnos[l] = -1; columns.Add(colName); cols[l] = colName; aliases.Add(thing.GetAlias(factory.Dialect, prop.Value.Table)); columnsLazy.Add(lazy); columnSelectables.Add(prop.IsSelectable); } l++; } propColumns.Add(cols); templates2.Add(forms); propColumnNumbers.Add(colnos); propFormulaNumbers.Add(formnos); joinedFetchesList.Add(prop.Value.FetchMode); cascades.Add(prop.CascadeStyle); } subclassColumnClosure = columns.ToArray(); subclassColumnAliasClosure = aliases.ToArray(); subclassColumnLazyClosure = columnsLazy.ToArray(); subclassColumnSelectableClosure = columnSelectables.ToArray(); subclassFormulaClosure = formulas.ToArray(); subclassFormulaTemplateClosure = formulaTemplates.ToArray(); subclassFormulaAliasClosure = formulaAliases.ToArray(); subclassFormulaLazyClosure = formulasLazy.ToArray(); subclassPropertyNameClosure = names.ToArray(); subclassPropertySubclassNameClosure = classes.ToArray(); subclassPropertyTypeClosure = types.ToArray(); subclassPropertyNullabilityClosure = propNullables.ToArray(); subclassPropertyFormulaTemplateClosure = templates2.ToArray(); subclassPropertyColumnNameClosure = propColumns.ToArray(); subclassPropertyColumnNumberClosure = propColumnNumbers.ToArray(); subclassPropertyFormulaNumberClosure = propFormulaNumbers.ToArray(); subclassPropertyCascadeStyleClosure = cascades.ToArray(); subclassPropertyFetchModeClosure = joinedFetchesList.ToArray(); propertyDefinedOnSubclass = definedBySubclass.ToArray(); #endregion // Handle any filters applied to the class level filterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry); temporaryIdTableName = persistentClass.TemporaryIdTableName; temporaryIdTableDDL = persistentClass.TemporaryIdTableDDL; }
public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { this.factory = factory; dialect = factory.Dialect; this.cache = cache; //sqlExceptionConverter = factory.SQLExceptionConverter; collectionType = collection.CollectionType; role = collection.Role; ownerClass = collection.OwnerClass; ownerPersister = factory.GetEntityPersister(ownerClass); queryLoaderName = collection.LoaderName; Alias alias = new Alias("__"); sqlOrderByString = collection.OrderBy; hasOrder = sqlOrderByString != null; sqlOrderByStringTemplate = hasOrder ? Template.RenderOrderByStringTemplate(sqlOrderByString, dialect, factory.SQLFunctionRegistry) : null; sqlWhereString = collection.Where; hasWhere = sqlWhereString != null; sqlWhereStringTemplate = hasWhere ? Template.RenderWhereStringTemplate(sqlWhereString, dialect, factory.SQLFunctionRegistry) : null; hasOrphanDelete = collection.OrphanDelete; batchSize = collection.BatchSize; isVersioned = collection.IsOptimisticLocked; keyType = collection.Key.Type; int keySpan = collection.Key.ColumnSpan; keyColumnNames = new string[keySpan]; string[] keyAliases = new string[keySpan]; int k = 0; foreach (Column col in collection.Key.ColumnCollection) { keyColumnNames[k] = col.GetQuotedName(dialect); keyAliases[k] = col.GetAlias(dialect); k++; } keyColumnAliases = alias.ToAliasStrings(keyAliases, dialect); //unquotedKeyColumnNames = StringHelper.Unquote( keyColumnAliases ); ISet distinctColumns = new HashedSet(); CheckColumnDuplication(distinctColumns, collection.Key.ColumnCollection); //isSet = collection.IsSet; //isSorted = collection.IsSorted; primitiveArray = collection.IsPrimitiveArray; array = collection.IsArray; subselectLoadable = collection.IsSubselectLoadable; IValue element = collection.Element; int elementSpan = element.ColumnSpan; Table table = collection.CollectionTable; fetchMode = element.FetchMode; elementType = element.Type; if (!collection.IsOneToMany) { CheckColumnDuplication(distinctColumns, element.ColumnCollection); } if (elementType.IsEntityType) { elementPersister = factory.GetEntityPersister(((EntityType) elementType).AssociatedClass); } else { elementPersister = null; } qualifiedTableName = table.GetQualifiedName(dialect, factory.DefaultSchema); elementColumnAliases = new string[elementSpan]; elementColumnNames = new string[elementSpan]; elementFormulaTemplates = new string[elementSpan]; elementFormulas = new string[elementSpan]; elementColumnIsSettable = new bool[elementSpan]; elementColumnIsInPrimaryKey = new bool[elementSpan]; int j = 0; foreach (ISelectable selectable in element.ColumnCollection) { elementColumnAliases[j] = selectable.GetAlias(dialect); if (selectable.IsFormula) { Formula form = (Formula) selectable; elementFormulaTemplates[j] = form.GetTemplate(dialect, factory.SQLFunctionRegistry); elementFormulas[j] = form.FormulaString; } else { Column col = (Column) selectable; elementColumnNames[j] = col.GetQuotedName(dialect); elementColumnIsSettable[j] = true; elementColumnIsInPrimaryKey[j] = !col.IsNullable; } j++; } hasIndex = collection.IsIndexed; if (hasIndex) { IndexedCollection indexedCollection = (IndexedCollection) collection; indexType = indexedCollection.Index.Type; int indexSpan = indexedCollection.Index.ColumnSpan; indexColumnNames = new string[indexSpan]; string[] indexAliases = new string[indexSpan]; int i = 0; foreach (Column indexCol in indexedCollection.Index.ColumnCollection) { indexAliases[i] = indexCol.GetAlias(dialect); indexColumnNames[i] = indexCol.GetQuotedName(dialect); i++; } indexColumnAliases = alias.ToAliasStrings(indexAliases, dialect); CheckColumnDuplication(distinctColumns, indexedCollection.Index.ColumnCollection); } else { indexType = null; indexColumnNames = null; indexColumnAliases = null; } hasIdentifier = collection.IsIdentified; if (hasIdentifier) { if (collection.IsOneToMany) { throw new MappingException("one-to-many collections with identifiers are not supported."); } IdentifierCollection idColl = (IdentifierCollection) collection; identifierType = idColl.Identifier.Type; Column col = null; foreach (Column column in idColl.Identifier.ColumnCollection) { col = column; break; } identifierColumnName = col.GetQuotedName(dialect); identifierColumnAlias = alias.ToAliasString(col.GetAlias(dialect), dialect); identifierGenerator = idColl.Identifier.CreateIdentifierGenerator(dialect); CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnCollection); } else { identifierType = null; identifierColumnName = null; identifierColumnAlias = null; identifierGenerator = null; } sqlInsertRowString = GenerateInsertRowString(); if (collection.CustomSQLInsert == null) { insertCallable = false; insertCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, sqlInsertRowString.ParameterTypes); insertCallable = collection.IsCustomInsertCallable; insertCheckStyle = collection.CustomSQLInsertCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable) : collection.CustomSQLInsertCheckStyle; } sqlUpdateRowString = GenerateUpdateRowString(); if (collection.CustomSQLUpdate == null) { updateCallable = false; updateCheckStyle = ExecuteUpdateResultCheckStyle.Count; } else { sqlUpdateRowString = new SqlCommandInfo(collection.CustomSQLUpdate, sqlUpdateRowString.ParameterTypes); updateCallable = collection.IsCustomUpdateCallable; updateCheckStyle = collection.CustomSQLUpdateCheckStyle == null ? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable) : collection.CustomSQLUpdateCheckStyle; } sqlDeleteRowString = GenerateDeleteRowString(); if (collection.CustomSQLDelete == null) { deleteCallable = false; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteRowString = new SqlCommandInfo(collection.CustomSQLDelete, sqlDeleteRowString.ParameterTypes); deleteCallable = collection.IsCustomDeleteCallable; deleteCheckStyle = ExecuteUpdateResultCheckStyle.None; } sqlDeleteString = GenerateDeleteString(); if (collection.CustomSQLDeleteAll == null) { deleteAllCallable = false; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } else { sqlDeleteString = new SqlCommandInfo(collection.CustomSQLDeleteAll, sqlDeleteString.ParameterTypes); deleteAllCallable = collection.IsCustomDeleteAllCallable; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.None; } isLazy = collection.IsLazy; isInverse = collection.IsInverse; if (collection.IsArray) { elementClass = ((Array) collection).ElementClass; } else { // for non-arrays, we don't need to know the element class elementClass = null; } if (elementType.IsComponentType) { elementPropertyMapping = new CompositeElementPropertyMapping( elementColumnNames, elementFormulaTemplates, (IAbstractComponentType) elementType, factory); } else if (!elementType.IsEntityType) { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } else { IEntityPersister persister = factory.GetEntityPersister(((EntityType) elementType).AssociatedClass); // Not all classpersisters implement IPropertyMapping! if (persister is IPropertyMapping) { elementPropertyMapping = (IPropertyMapping) persister; } else { elementPropertyMapping = new ElementPropertyMapping(elementColumnNames, elementType); } } // Handle any filters applied to this collection filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry); // Handle any filters applied to this collection for many-to-many manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry); manyToManyWhereString = StringHelper.IsNotEmpty(collection.ManyToManyWhere) ? "( " + collection.ManyToManyWhere + " )" : null; manyToManyWhereTemplate = manyToManyWhereString == null ? null : Template.RenderWhereStringTemplate(manyToManyWhereString, factory.Dialect, factory.SQLFunctionRegistry); // , factory.getSqlFunctionRegistry() ); manyToManyOrderByString = collection.ManyToManyOrdering; manyToManyOrderByTemplate = manyToManyOrderByString == null ? null : Template.RenderOrderByStringTemplate(manyToManyOrderByString, factory.Dialect, factory.SQLFunctionRegistry); // , factory.getSqlFunctionRegistry() ); InitCollectionPropertyMap(); }
internal void SetCacheConcurrencyStrategy( System.Type clazz, ICacheConcurrencyStrategy concurrencyStrategy, string region ) { RootClass rootClass = GetRootClassMapping( clazz ); rootClass.Cache = concurrencyStrategy; caches[ rootClass.MappedClass.FullName ] = concurrencyStrategy; }
public MyCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) : base(collection, cache, factory) { }
internal void SetCacheConcurrencyStrategy( string collectionRole, ICacheConcurrencyStrategy concurrencyStrategy, string region ) { // TODO: this is ported from H2.1.8, but the implementation looks // very strange to me - region parameter is ignored, // collection.Role is used instead of collectionRole, etc. NHibernate.Mapping.Collection collection = GetCollectionMapping( collectionRole ); collection.Cache = concurrencyStrategy; if( caches.Contains( collection.Role ) ) { throw new MappingException( "duplicate cache region " + collection.Role ); } caches.Add( collection.Role, concurrencyStrategy ); }
public SingleTableEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) : base(persistentClass, cache, factory) { #region CLASS + TABLE joinSpan = persistentClass.JoinClosureSpan + 1; qualifiedTableNames = new string[joinSpan]; isInverseTable = new bool[joinSpan]; isNullableTable = new bool[joinSpan]; keyColumnNames = new string[joinSpan][]; Table table = persistentClass.RootTable; qualifiedTableNames[0] = table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); isInverseTable[0] = false; isNullableTable[0] = false; keyColumnNames[0] = IdentifierColumnNames; cascadeDeleteEnabled = new bool[joinSpan]; // Custom sql customSQLInsert = new SqlString[joinSpan]; customSQLUpdate = new SqlString[joinSpan]; customSQLDelete = new SqlString[joinSpan]; insertCallable = new bool[joinSpan]; updateCallable = new bool[joinSpan]; deleteCallable = new bool[joinSpan]; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; customSQLInsert[0] = persistentClass.CustomSQLInsert; insertCallable[0] = customSQLInsert[0] != null && persistentClass.IsCustomInsertCallable; insertResultCheckStyles[0] = persistentClass.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]); customSQLUpdate[0] = persistentClass.CustomSQLUpdate; updateCallable[0] = customSQLUpdate[0] != null && persistentClass.IsCustomUpdateCallable; updateResultCheckStyles[0] = persistentClass.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]); customSQLDelete[0] = persistentClass.CustomSQLDelete; deleteCallable[0] = customSQLDelete[0] != null && persistentClass.IsCustomDeleteCallable; deleteResultCheckStyles[0] = persistentClass.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]); #endregion #region JOINS int j = 1; foreach (Join join in persistentClass.JoinClosureIterator) { qualifiedTableNames[j] = join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName); isInverseTable[j] = join.IsInverse; isNullableTable[j] = join.IsOptional; cascadeDeleteEnabled[j] = join.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete; customSQLInsert[j] = join.CustomSQLInsert; insertCallable[j] = customSQLInsert[j] != null && join.IsCustomInsertCallable; insertResultCheckStyles[j] = join.CustomSQLInsertCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[j], insertCallable[j]); customSQLUpdate[j] = join.CustomSQLUpdate; updateCallable[j] = customSQLUpdate[j] != null && join.IsCustomUpdateCallable; updateResultCheckStyles[j] = join.CustomSQLUpdateCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[j], updateCallable[j]); customSQLDelete[j] = join.CustomSQLDelete; deleteCallable[j] = customSQLDelete[j] != null && join.IsCustomDeleteCallable; deleteResultCheckStyles[j] = join.CustomSQLDeleteCheckStyle ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[j], deleteCallable[j]); IEnumerable <Column> enumerableKeyCol = new SafetyEnumerable <Column>(join.Key.ColumnIterator); List <string> kcName = new List <string>(join.Key.ColumnSpan); foreach (Column col in enumerableKeyCol) { kcName.Add(col.GetQuotedName(factory.Dialect)); } keyColumnNames[j] = kcName.ToArray(); j++; } constraintOrderedTableNames = new string[qualifiedTableNames.Length]; constraintOrderedKeyColumnNames = new string[qualifiedTableNames.Length][]; for (int i = qualifiedTableNames.Length - 1, position = 0; i >= 0; i--, position++) { constraintOrderedTableNames[position] = qualifiedTableNames[i]; constraintOrderedKeyColumnNames[position] = keyColumnNames[i]; } spaces = ArrayHelper.Join(qualifiedTableNames, ArrayHelper.ToStringArray(persistentClass.SynchronizedTables)); bool lazyAvailable = IsInstrumented(EntityMode.Poco); bool hasDeferred = false; List <string> subclassTables = new List <string>(); List <string[]> joinKeyColumns = new List <string[]>(); List <bool> isConcretes = new List <bool>(); List <bool> isDeferreds = new List <bool>(); List <bool> isInverses = new List <bool>(); List <bool> isNullables = new List <bool>(); List <bool> isLazies = new List <bool>(); subclassTables.Add(qualifiedTableNames[0]); joinKeyColumns.Add(IdentifierColumnNames); isConcretes.Add(true); isDeferreds.Add(false); isInverses.Add(false); isNullables.Add(false); isLazies.Add(false); foreach (Join join in persistentClass.SubclassJoinClosureIterator) { isConcretes.Add(persistentClass.IsClassOrSuperclassJoin(join)); isDeferreds.Add(join.IsSequentialSelect); isInverses.Add(join.IsInverse); isNullables.Add(join.IsOptional); isLazies.Add(lazyAvailable && join.IsLazy); if (join.IsSequentialSelect && !persistentClass.IsClassOrSuperclassJoin(join)) { hasDeferred = true; } subclassTables.Add(join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName)); IEnumerable <Column> enumerableKeyCol = new SafetyEnumerable <Column>(join.Key.ColumnIterator); List <string> keyCols = new List <string>(join.Key.ColumnSpan); foreach (Column col in enumerableKeyCol) { keyCols.Add(col.GetQuotedName(factory.Dialect)); } joinKeyColumns.Add(keyCols.ToArray()); } subclassTableSequentialSelect = isDeferreds.ToArray(); subclassTableNameClosure = subclassTables.ToArray(); subclassTableIsLazyClosure = isLazies.ToArray(); subclassTableKeyColumnClosure = joinKeyColumns.ToArray(); isClassOrSuperclassTable = isConcretes.ToArray(); isInverseSubclassTable = isInverses.ToArray(); isNullableSubclassTable = isNullables.ToArray(); hasSequentialSelects = hasDeferred; #endregion #region DISCRIMINATOR if (persistentClass.IsPolymorphic) { IValue discrimValue = persistentClass.Discriminator; if (discrimValue == null) { throw new MappingException("Discriminator mapping required for single table polymorphic persistence"); } forceDiscriminator = persistentClass.IsForceDiscriminator; IEnumerator <ISelectable> iSel = discrimValue.ColumnIterator.GetEnumerator(); iSel.MoveNext(); ISelectable selectable = iSel.Current; if (discrimValue.HasFormula) { Formula formula = (Formula)selectable; discriminatorFormula = formula.FormulaString; discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); discriminatorColumnName = null; discriminatorAlias = Discriminator_Alias; } else { Column column = (Column)selectable; discriminatorColumnName = column.GetQuotedName(factory.Dialect); discriminatorAlias = column.GetAlias(factory.Dialect, persistentClass.RootTable); discriminatorFormula = null; discriminatorFormulaTemplate = null; } discriminatorType = persistentClass.Discriminator.Type; if (persistentClass.IsDiscriminatorValueNull) { discriminatorValue = NullDiscriminator; discriminatorSQLValue = InFragment.Null; discriminatorInsertable = false; } else if (persistentClass.IsDiscriminatorValueNotNull) { discriminatorValue = NotNullDiscriminator; discriminatorSQLValue = InFragment.NotNull; discriminatorInsertable = false; } else { discriminatorInsertable = persistentClass.IsDiscriminatorInsertable && !discrimValue.HasFormula; try { IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType; discriminatorValue = dtype.StringToObject(persistentClass.DiscriminatorValue); discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue, factory.Dialect); } catch (InvalidCastException cce) { throw new MappingException( string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce); } catch (Exception e) { throw new MappingException("Could not format discriminator value to SQL string of entity " + persistentClass.EntityName, e); } } } else { forceDiscriminator = false; discriminatorInsertable = false; discriminatorColumnName = null; discriminatorAlias = null; discriminatorType = null; discriminatorValue = null; discriminatorSQLValue = null; discriminatorFormula = null; discriminatorFormulaTemplate = null; } #endregion #region PROPERTIES propertyTableNumbers = new int[PropertySpan]; int i2 = 0; foreach (Property prop in persistentClass.PropertyClosureIterator) { propertyTableNumbers[i2++] = persistentClass.GetJoinNumber(prop); } List <int> columnJoinNumbers = new List <int>(); List <int> formulaJoinedNumbers = new List <int>(); List <int> propertyJoinNumbers = new List <int>(); foreach (Property prop in persistentClass.SubclassPropertyClosureIterator) { int join = persistentClass.GetJoinNumber(prop); propertyJoinNumbers.Add(join); //propertyTableNumbersByName.put( prop.getName(), join ); propertyTableNumbersByNameAndSubclass[prop.PersistentClass.EntityName + '.' + prop.Name] = join; foreach (ISelectable thing in prop.ColumnIterator) { if (thing.IsFormula) { formulaJoinedNumbers.Add(join); } else { columnJoinNumbers.Add(join); } } } subclassColumnTableNumberClosure = columnJoinNumbers.ToArray(); subclassFormulaTableNumberClosure = formulaJoinedNumbers.ToArray(); subclassPropertyTableNumberClosure = propertyJoinNumbers.ToArray(); int subclassSpan = persistentClass.SubclassSpan + 1; subclassClosure = new string[subclassSpan]; subclassClosure[0] = EntityName; if (persistentClass.IsPolymorphic) { subclassesByDiscriminatorValue[discriminatorValue] = EntityName; } #endregion #region SUBCLASSES if (persistentClass.IsPolymorphic) { int k = 1; foreach (Subclass sc in persistentClass.SubclassIterator) { subclassClosure[k++] = sc.EntityName; if (sc.IsDiscriminatorValueNull) { subclassesByDiscriminatorValue[NullDiscriminator] = sc.EntityName; } else if (sc.IsDiscriminatorValueNotNull) { subclassesByDiscriminatorValue[NotNullDiscriminator] = sc.EntityName; } else { if (discriminatorType == null) { throw new MappingException("Not available discriminator type of entity " + persistentClass.EntityName); } try { IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType; subclassesByDiscriminatorValue[dtype.StringToObject(sc.DiscriminatorValue)] = sc.EntityName; } catch (InvalidCastException cce) { throw new MappingException( string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce); } catch (Exception e) { throw new MappingException("Error parsing discriminator value of entity " + persistentClass.EntityName, e); } } } } #endregion InitLockers(); InitSubclassPropertyAliasesMap(persistentClass); PostConstruct(mapping); }