📄 abstractentitypersister.java
字号:
PreparedStatement ps = null;
ResultSet rs = null;
try {
final String lazySelect = getSQLLazySelectString();
if (lazySelect!=null) {
// null sql means the lazy properties do not map to
// columns or formulas (eg. one-to-one associations)
ps = session.getBatcher().prepareSelectStatement(lazySelect);
getIdentifierType().nullSafeSet( ps, id, 1, session );
rs = ps.executeQuery();
rs.next();
}
final Object[] snapshot = entry.getLoadedState();
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;
}
}
if (rs!=null) rs.close();
}
finally {
if (ps!=null) session.getBatcher().closeStatement(ps);
}
log.trace( "done initializing lazy properties" );
return result;
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not initialize lazy properties: " +
MessageHelper.infoString( this, id, getFactory() ),
getSQLLazySelectString()
);
}
}
private Object initializeLazyPropertiesFromCache(
final String fieldName,
final Object entity,
final SessionImplementor session,
final EntityEntry entry,
final CacheEntry cacheEntry
) {
log.trace("initializing lazy properties from second-level cache");
Object result = null;
Serializable[] disassembledValues = cacheEntry.getDisassembledState();
final Object[] snapshot = entry.getLoadedState();
for ( int j = 0; j < lazyPropertyNames.length; j++ ) {
final Object propValue = lazyPropertyTypes[j].assemble(
disassembledValues[ lazyPropertyNumbers[j] ],
session,
entity
);
if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) {
result = propValue;
}
}
log.trace( "done initializing lazy properties" );
return result;
}
private boolean initializeLazyProperty(
final String fieldName,
final Object entity,
final SessionImplementor session,
final Object[] snapshot,
final int j,
final Object propValue
) {
setPropertyValue( entity, lazyPropertyNumbers[j], propValue, session.getEntityMode() );
snapshot[ lazyPropertyNumbers[j] ] = lazyPropertyTypes[j].deepCopy( propValue, session.getEntityMode(), factory );
return fieldName.equals( lazyPropertyNames[j] );
}
public boolean isBatchable() {
return optimisticLockMode()==Versioning.OPTIMISTIC_LOCK_NONE ||
( !isVersioned() && optimisticLockMode()==Versioning.OPTIMISTIC_LOCK_VERSION ) ||
getFactory().getSettings().isJdbcBatchVersionedData();
}
public Serializable[] getQuerySpaces() {
return getPropertySpaces();
}
protected Set getLazyProperties() {
return lazyProperties;
}
private String getLockString(LockMode lockMode) {
return ( String ) lockers.get( lockMode );
}
public boolean isBatchLoadable() {
return batchSize > 1;
}
public String[] getIdentifierColumnNames() {
return rootTableKeyColumnNames;
}
protected int getIdentifierColumnSpan() {
return identifierColumnSpan;
}
protected String[] getIdentifierAliases() {
return identifierAliases;
}
public String getVersionColumnName() {
return versionColumnName;
}
protected String getVersionedTableName() {
return getTableName( 0 );
}
protected boolean[] getSubclassColumnLazyiness() {
return subclassColumnLazyClosure;
}
protected boolean[] getSubclassFormulaLazyiness() {
return subclassFormulaLazyClosure;
}
/**
* We can't immediately add to the cache if we have formulas
* which must be evaluated, or if we have the possibility of
* two concurrent updates to the same item being merged on
* the database. This can happen if (a) the item is not
* versioned and either (b) we have dynamic update enabled
* or (c) we have multiple tables holding the state of the
* item.
*/
public boolean isCacheInvalidationRequired() {
return hasFormulaProperties() ||
( !isVersioned() && ( entityMetamodel.isDynamicUpdate() || getTableSpan() > 1 ) );
}
public boolean isLazyPropertiesCacheable() {
return isLazyPropertiesCacheable;
}
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 unqoting and missing aliases..
return new Alias( suffix ).toAliasStrings( getIdentifierAliases() );
}
public String[] getPropertyAliases(String suffix, int i) {
// NOTE: this assumes something about how propertySelectFragment is implemented by the subclass!
return new Alias( suffix ).toUnquotedAliasStrings( propertyColumnAliases[i] );
}
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 unqoting and missing aliases..
return entityMetamodel.hasSubclasses() ?
new Alias( suffix ).toAliasString( getDiscriminatorAlias() ) :
null;
}
public String identifierSelectFragment(String name, String suffix) {
return new SelectFragment()
.setSuffix( suffix )
.addColumns( name, getIdentifierColumnNames(), getIdentifierAliases() )
.toFragmentString()
.substring( 2 ); //strip leading ", "
}
public String propertySelectFragment(String name, String suffix, boolean allProperties) {
SelectFragment select = new SelectFragment()
.setSuffix( suffix )
.setUsedAliases( getIdentifierAliases() );
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
String[] columnAliases = getSubclassColumnAliasClosure();
String[] columns = getSubclassColumnClosure();
for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) {
boolean 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 = getSubclassFormulaTableNumberClosure();
String[] formulaTemplates = getSubclassFormulaTemplateClosure();
String[] formulaAliases = getSubclassFormulaAliasClosure();
for ( int i = 0; i < getSubclassFormulaTemplateClosure().length; i++ ) {
boolean 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, ROWID_ALIAS );
return select.toFragmentString();
}
public Object[] getDatabaseSnapshot(Serializable id, SessionImplementor session)
throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "Getting current persistent state for: " + MessageHelper.infoString( this, id, getFactory() ) );
}
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( getSQLSnapshotSelectString() );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
//if ( isVersioned() ) getVersionType().nullSafeSet( ps, version, getIdentifierColumnSpan()+1, session );
ResultSet rs = ps.executeQuery();
try {
//if there is no resulting row, return null
if ( !rs.next() ) return null;
//otherwise return the "hydrated" state (ie. associations are not resolved)
Type[] types = getPropertyTypes();
Object[] values = new Object[types.length];
boolean[] includeProperty = getPropertyUpdateability();
for ( int i = 0; i < types.length; i++ ) {
if ( includeProperty[i] ) {
values[i] = types[i].hydrate( rs, getPropertyAliases( "", i ), session, null ); //null owner ok??
}
}
return values;
}
finally {
rs.close();
}
}
finally {
session.getBatcher().closeStatement( ps );
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not retrieve snapshot: " +
MessageHelper.infoString( this, id, getFactory() ),
getSQLSnapshotSelectString()
);
}
}
/**
* Generate the SQL that selects the version number by id
*/
protected String generateSelectVersionString() {
SimpleSelect select = new SimpleSelect( getFactory().getDialect() )
.setTableName( getVersionedTableName() );
if ( isVersioned() ) {
select.addColumn( versionColumnName );
}
else {
select.addColumns( rootTableKeyColumnNames );
}
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "get version " + getEntityName() );
}
return select.addCondition( rootTableKeyColumnNames, "=?" ).toStatementString();
}
protected String generateInsertGeneratedValuesSelectString() {
return generateGeneratedValuesSelectString( getPropertyInsertGeneration() );
}
protected String generateUpdateGeneratedValuesSelectString() {
return generateGeneratedValuesSelectString( getPropertyUpdateGeneration() );
}
private String generateGeneratedValuesSelectString(boolean[] inclusions) {
Select select = new Select( getFactory().getDialect() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "get generated state " + getEntityName() );
}
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
String selectClause = concretePropertySelectFragment( getRootAlias(), inclusions );
selectClause = selectClause.substring( 2 );
String fromClause = fromTableFragment( getRootAlias() ) +
fromJoinFragment( getRootAlias(), true, false );
String whereClause = new StringBuffer()
.append( StringHelper.join( "=? and ", aliasedIdColumns ) )
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
return select.setSelectClause( selectClause )
.setFromClause( fromClause )
.setOuterJoins( "", "" )
.setWhereClause( whereClause )
.toStatementString();
}
protected String concretePropertySelectFragment(String alias, boolean[] includeProperty) {
int propertyCount = getPropertyNames().length;
int[] propertyTableNumbers = getPropertyTableNumbersInSelect();
SelectFragment frag = new SelectFragment();
for ( int i = 0; i < propertyCount; i++ ) {
if ( includeProperty[i] ) { //ie. updateable, not a formula
frag.addColumns(
generateTableAlias( alias, propertyTableNumbers[i] ),
propertyColumnNames[i],
propertyColumnAliases[i]
);
frag.addFormulas(
generateTableAlias( alias, propertyTableNumbers[i] ),
propertyColumnFormulaTemplates[i],
propertyColumnAliases[i]
);
}
}
return frag.toFragmentString();
}
protected String generateSnapshotSelectString() {
//TODO: should we use SELECT .. FOR UPDATE?
Select select = new Select( getFactory().getDialect() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "get current state " + getEntityName() );
}
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
String selectClause = StringHelper.join( ", ", aliasedIdColumns ) +
concretePropertySelectFragment( getRootAlias(), getPropertyUpdateability() );
String fromClause = fromTableFragment( getRootAlias() ) +
fromJoinFragment( getRootAlias(), true, false );
String whereClause = new StringBuffer()
.append( StringHelper.join( "=? and ",
aliasedIdColumns ) )
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
/*if ( isVersioned() ) {
where.append(" and ")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -