📄 abstractentitypersister.cs
字号:
for (int j = 0; j < lazyPropertyNames.Length; j++)
{
object propValue = lazyPropertyTypes[j].NullSafeGet(rs, lazyPropertyColumnAliases[j], session, entity);
if (InitializeLazyProperty(fieldName, entity, session, snapshot, j, propValue))
{
result = propValue;
}
}
}
finally
{
session.Batcher.CloseCommand(ps, rs);
}
log.Debug("done initializing lazy properties");
return result;
}
catch (DbException sqle)
{
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, sqle, "could not initialize lazy properties: " + MessageHelper.InfoString(this, id, Factory), SQLLazySelectString);
}
}
private object InitializeLazyPropertiesFromCache(string fieldName, object entity, ISessionImplementor session, EntityEntry entry, CacheEntry cacheEntry)
{
log.Debug("initializing lazy properties from second-level cache");
object result = null;
object[] disassembledValues = cacheEntry.DisassembledState;
object[] snapshot = entry.LoadedState;
for (int j = 0; j < lazyPropertyNames.Length; j++)
{
object propValue = lazyPropertyTypes[j].Assemble(disassembledValues[lazyPropertyNumbers[j]], session, entity);
if (InitializeLazyProperty(fieldName, entity, session, snapshot, j, propValue))
{
result = propValue;
}
}
log.Debug("done initializing lazy properties");
return result;
}
private bool InitializeLazyProperty(string fieldName, object entity, ISessionImplementor session, object[] snapshot, int j, object propValue)
{
SetPropertyValue(entity, lazyPropertyNumbers[j], propValue, session.EntityMode);
if (snapshot != null)
{
// object have been loaded with setReadOnly(true); HHH-2236
snapshot[lazyPropertyNumbers[j]] = lazyPropertyTypes[j].DeepCopy(propValue, session.EntityMode, factory);
}
return fieldName.Equals(lazyPropertyNames[j]);
}
public string[] IdentifierAliases
{
get { return identifierAliases; }
}
public string SelectFragment(string alias, string suffix)
{
return IdentifierSelectFragment(alias, suffix) + PropertySelectFragment(alias, suffix, false);
}
public string[] GetIdentifierAliases(string suffix)
{
// NOTE: this assumes something about how PropertySelectFragment is implemented by the subclass!
// was toUnqotedAliasStrings( getIdentiferColumnNames() ) before - now tried
// to remove that unquoting and missing aliases..
return new Alias(suffix).ToAliasStrings(IdentifierAliases, factory.Dialect);
}
public string[] GetPropertyAliases(string suffix, int i)
{
// NOTE: this assumes something about how pPropertySelectFragment is implemented by the subclass!
return new Alias(suffix).ToUnquotedAliasStrings(propertyColumnAliases[i], factory.Dialect);
}
public string GetDiscriminatorAlias(string suffix)
{
// NOTE: this assumes something about how PropertySelectFragment is implemented by the subclass!
// was toUnqotedAliasStrings( getdiscriminatorColumnName() ) before - now tried
// to remove that unquoting and missing aliases..
return entityMetamodel.HasSubclasses ? new Alias(suffix).ToAliasString(DiscriminatorAlias, factory.Dialect) : null;
}
public virtual string IdentifierSelectFragment(string name, string suffix)
{
return new SelectFragment(factory.Dialect)
.SetSuffix(suffix)
.AddColumns(name, IdentifierColumnNames, IdentifierAliases)
.ToSqlStringFragment(false);
}
public string PropertySelectFragment(string name, string suffix, bool allProperties)
{
SelectFragment select = new SelectFragment(Factory.Dialect)
.SetSuffix(suffix)
.SetUsedAliases(IdentifierAliases);
int[] columnTableNumbers = SubclassColumnTableNumberClosure;
string[] columnAliases = SubclassColumnAliasClosure;
string[] columns = SubclassColumnClosure;
for (int i = 0; i < columns.Length; i++)
{
bool selectable = (allProperties || !subclassColumnLazyClosure[i]) &&
!IsSubclassTableSequentialSelect(columnTableNumbers[i]) &&
subclassColumnSelectableClosure[i];
if (selectable)
{
string subalias = GenerateTableAlias(name, columnTableNumbers[i]);
select.AddColumn(subalias, columns[i], columnAliases[i]);
}
}
int[] formulaTableNumbers = SubclassFormulaTableNumberClosure;
string[] formulaTemplates = SubclassFormulaTemplateClosure;
string[] formulaAliases = SubclassFormulaAliasClosure;
for (int i = 0; i < formulaTemplates.Length; i++)
{
bool selectable = (allProperties || !subclassFormulaLazyClosure[i]) &&
!IsSubclassTableSequentialSelect(formulaTableNumbers[i]);
if (selectable)
{
string subalias = GenerateTableAlias(name, formulaTableNumbers[i]);
select.AddFormula(subalias, formulaTemplates[i], formulaAliases[i]);
}
}
if (entityMetamodel.HasSubclasses)
AddDiscriminatorToSelect(select, name, suffix);
if (HasRowId)
select.AddColumn(name, rowIdName, Loadable.RowIdAlias);
return select.ToSqlStringFragment();
}
public object[] GetDatabaseSnapshot(object id, ISessionImplementor session)
{
if (log.IsDebugEnabled)
{
log.Debug("Getting current persistent state for: " + MessageHelper.InfoString(this, id, Factory));
}
try
{
IDbCommand st = session.Batcher.PrepareCommand(CommandType.Text, SQLSnapshotSelectString, IdentifierType.SqlTypes(factory));
IDataReader rs = null;
try
{
IdentifierType.NullSafeSet(st, id, 0, session);
rs = session.Batcher.ExecuteReader(st);
if (!rs.Read())
{
//if there is no resulting row, return null
return null;
}
//otherwise return the "hydrated" state (ie. associations are not resolved)
IType[] types = PropertyTypes;
object[] values = new object[types.Length];
bool[] includeProperty = PropertyUpdateability;
for (int i = 0; i < types.Length; i++)
{
if (includeProperty[i])
{
values[i] = types[i].Hydrate(rs, GetPropertyAliases(string.Empty, i), session, null); //null owner ok??
}
}
return values;
}
finally
{
session.Batcher.CloseCommand(st, rs);
}
}
catch (DbException sqle)
{
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, sqle, "could not retrieve snapshot: " + MessageHelper.InfoString(this, id, Factory), SQLSnapshotSelectString);
}
}
/// <summary>
/// Generate the SQL that selects the version number by id
/// </summary>
protected SqlString GenerateSelectVersionString()
{
SqlSimpleSelectBuilder builder = new SqlSimpleSelectBuilder(Factory.Dialect, factory)
.SetTableName(VersionedTableName);
if (IsVersioned)
builder.AddColumn(versionColumnName);
else
builder.AddColumns(rootTableKeyColumnNames);
if (Factory.Settings.IsCommentsEnabled)
{
builder.SetComment("get version " + EntityName);
}
return builder.AddWhereFragment(rootTableKeyColumnNames, IdentifierType, " = ").ToSqlString();
}
protected SqlString GenerateInsertGeneratedValuesSelectString()
{
return GenerateGeneratedValuesSelectString(PropertyInsertGenerationInclusions);
}
protected SqlString GenerateUpdateGeneratedValuesSelectString()
{
return GenerateGeneratedValuesSelectString(PropertyUpdateGenerationInclusions);
}
private SqlString GenerateGeneratedValuesSelectString(ValueInclusion[] inclusions)
{
SqlSelectBuilder select = new SqlSelectBuilder(Factory);
if (Factory.Settings.IsCommentsEnabled)
{
select.SetComment("get generated state " + EntityName);
}
string[] aliasedIdColumns = StringHelper.Qualify(RootAlias, IdentifierColumnNames);
// Here we render the select column list based on the properties defined as being generated.
// For partial component generation, we currently just re-select the whole component
// rather than trying to handle the individual generated portions.
string selectClause = ConcretePropertySelectFragment(RootAlias, inclusions);
selectClause = selectClause.Substring(2);
string fromClause = FromTableFragment(RootAlias) + FromJoinFragment(RootAlias, true, false);
SqlString whereClause = new SqlStringBuilder()
.Add(StringHelper.Join(new SqlString("=", Parameter.Placeholder, " and "), aliasedIdColumns))
.Add("=").AddParameter()
.Add(WhereJoinFragment(RootAlias, true, false))
.ToSqlString();
return select.SetSelectClause(selectClause)
.SetFromClause(fromClause)
.SetOuterJoins(SqlString.Empty, SqlString.Empty)
.SetWhereClause(whereClause)
.ToSqlString();
}
protected string ConcretePropertySelectFragment(string alias, ValueInclusion[] inclusions)
{
return ConcretePropertySelectFragment(alias, new NoneInclusionChecker(inclusions));
}
protected string ConcretePropertySelectFragment(string alias, bool[] includeProperty)
{
return ConcretePropertySelectFragment(alias, new FullInclusionChecker(includeProperty));
}
protected string ConcretePropertySelectFragment(string alias, IInclusionChecker inclusionChecker)
{
int propertyCount = PropertyNames.Length;
int[] propertyTableNumbers = PropertyTableNumbersInSelect;
SelectFragment frag = new SelectFragment(Factory.Dialect);
for (int i = 0; i < propertyCount; i++)
{
if (inclusionChecker.IncludeProperty(i))
{
frag.AddColumns(GenerateTableAlias(alias, propertyTableNumbers[i]), propertyColumnNames[i], propertyColumnAliases[i]);
frag.AddFormulas(GenerateTableAlias(alias, propertyTableNumbers[i]), propertyColumnFormulaTemplates[i], propertyColumnAliases[i]);
}
}
return frag.ToFragmentString();
}
protected virtual SqlString GenerateSnapshotSelectString()
{
//TODO: should we use SELECT .. FOR UPDATE?
SqlSelectBuilder select = new SqlSelectBuilder(Factory);
if (Factory.Settings.IsCommentsEnabled)
{
select.SetComment("get current state " + EntityName);
}
string[] aliasedIdColumns = StringHelper.Qualify(RootAlias, IdentifierColumnNames);
string selectClause = StringHelper.Join(StringHelper.CommaSpace, aliasedIdColumns)
+ ConcretePropertySelectFragment(RootAlias, PropertyUpdateability);
SqlString fromClause = new SqlString(FromTableFragment(RootAlias)) +
FromJoinFragment(RootAlias, true, false);
SqlString joiner = new SqlString("=", Parameter.Placeholder, " and ");
SqlStringBuilder whereClauseBuilder = new SqlStringBuilder()
.Add(StringHelper.Join(joiner, aliasedIdColumns))
.Add("=")
.AddParameter()
.Add(WhereJoinFragment(RootAlias, true, false));
// H3.2 the Snapshot is what we found in DB without take care on version
//if (IsVersioned)
//{
// whereClauseBuilder.Add(" and ")
// .Add(VersionColumnName)
// .Add("=")
// .AddParameter();
//}
return select.SetSelectClause(selectClause)
.SetFromClause(fromClause)
.SetOuterJoins(SqlString.Empty, SqlString.Empty)
.SetWhereClause(whereClauseBuilder.ToSqlString())
.ToSqlString();
}
public object ForceVersionIncrement(object id, object currentVersion, ISessionImplementor session)
{
if (!IsVersioned)
throw new AssertionFailure("cannot force version increment on non-versioned entity");
if (IsVersionPropertyGenerated)
{
// the difficulty here is exactly what do we update in order to
// force the version to be incremented in the db...
throw new HibernateException("LockMode.Force is currently not supported for generated version properties");
}
object nextVersion = VersionType.Next(currentVersion, session);
if (log.IsDebugEnabled)
{
log.Debug("Forcing version increment [" +
MessageHelper.InfoString(this, id, Factory) + "; " +
VersionType.ToLoggableString(currentVersion, Factory) + " -> " +
VersionType.ToLoggableString(nextVersion, Factory) + "]");
}
IExpectation expectation = Expectations.AppropriateExpectation(updateResultCheckStyles[0]);
// todo : cache this sql...
SqlCommandInfo versionIncrementCommand = GenerateVersionIncrementUpdateString();
try
{
IDbCommand st = session.Batcher.PrepareCommand(versionIncrementCommand.CommandType, versionIncrementCommand.Text, versionIncrementCommand.ParameterTypes);
try
{
VersionType.NullSafeSet(st, nextVersion, 0, session);
IdentifierType.NullSafeSet(st, id, 1, session);
VersionType.NullSafeSet(st, currentVersion, 1 + IdentifierColumnSpan, session);
Check(session.Batcher.ExecuteNonQuery(st), id, 0, expectation, st);
}
finally
{
session.Batcher.CloseCommand(st, null);
}
}
catch (DbException sqle)
{
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, sqle,
"could not retrieve version: " + MessageHelper.InfoString(this, id, Factory),
VersionSelectString);
}
return nextVersion;
}
private SqlCommandInfo GenerateVersionIncrementUpdateString()
{
SqlUpdateBuilder update = new SqlUpdateBuilder(Factory.Dialect, Factory);
update.SetTableName(GetTableName(0));
if (Factory.Settings.IsCommentsEnabled)
{
update.SetComment("forced version increment");
}
update.AddColumn(VersionColumnName, VersionType);
update.SetIdentityColumn(IdentifierColumnNames, IdentifierType);
update.SetVersionColumn(new string[] { VersionColumnName }, VersionType);
return update.ToSqlCommandInfo();
}
/// <summary>
/// Retrieve the version number
/// </summary>
public object GetCurrentVersion(object id, ISessionImplementor session)
{
if (log.IsDebugEnabled)
{
log.Debug("Getting version: " + MessageHelper.InfoString(this, id, Factory));
}
try
{
IDbCommand st = session.Batcher.PrepareQueryCommand(CommandType.Text, VersionSelectString, IdentifierType.SqlTypes(Factory));
IDataReader rs = null;
try
{
IdentifierType.NullSafeSet(st, id, 0, session);
rs = session.Batcher.ExecuteReader(st);
if (!rs.Read())
{
return null;
}
if (!IsVersioned)
{
return this;
}
return VersionType.NullSafeGet(rs, VersionColumnName, session, null);
}
finally
{
session.Batcher.CloseCommand(st, rs);
}
}
catch (DbException sqle)
{
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, sqle,
"could not retrieve version: " + MessageHelper.InfoString(this, id, Factory),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -