📄 abstractentitypersister.java
字号:
Property prop = ( Property ) propertyIterator.next();
String propname = path == null ? prop.getName() : path + "." + prop.getName();
if ( prop.isComposite() ) {
Component component = ( Component ) prop.getValue();
Iterator compProps = component.getPropertyIterator();
internalInitSubclassPropertyAliasesMap( propname, compProps );
}
else {
String[] aliases = new String[prop.getColumnSpan()];
String[] cols = new String[prop.getColumnSpan()];
Iterator colIter = prop.getColumnIterator();
int l = 0;
while ( colIter.hasNext() ) {
Selectable thing = ( Selectable ) colIter.next();
aliases[l] = thing.getAlias( getFactory().getDialect(), prop.getValue().getTable() );
cols[l] = thing.getText( getFactory().getDialect() ); // TODO: skip formulas?
l++;
}
subclassPropertyAliases.put( propname, aliases );
subclassPropertyColumnNames.put( propname, cols );
}
}
}
public Object loadByUniqueKey(String propertyName, Object uniqueKey, SessionImplementor session)
throws HibernateException {
return getAppropriateUniqueKeyLoader( propertyName, session.getEnabledFilters() )
.loadByUniqueKey( session, uniqueKey );
}
private EntityLoader getAppropriateUniqueKeyLoader(String propertyName, Map enabledFilters) {
final boolean useStaticLoader = ( enabledFilters == null || enabledFilters.isEmpty() )
&& propertyName.indexOf('.')<0; //ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
if ( useStaticLoader ) {
return (EntityLoader) uniqueKeyLoaders.get( propertyName );
}
else {
return createUniqueKeyLoader(
propertyMapping.toType(propertyName),
propertyMapping.toColumns(propertyName),
enabledFilters
);
}
}
public int getPropertyIndex(String propertyName) {
return entityMetamodel.getPropertyIndex(propertyName);
}
protected void createUniqueKeyLoaders() throws MappingException {
Type[] propertyTypes = getPropertyTypes();
String[] propertyNames = getPropertyNames();
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( propertyUniqueness[i] ) {
//don't need filters for the static loaders
uniqueKeyLoaders.put(
propertyNames[i],
createUniqueKeyLoader(
propertyTypes[i],
getPropertyColumnNames( i ),
CollectionHelper.EMPTY_MAP
)
);
//TODO: create uk loaders for component properties
}
}
}
private EntityLoader createUniqueKeyLoader(Type uniqueKeyType, String[] columns, Map enabledFilters) {
if ( uniqueKeyType.isEntityType() ) {
String className = ( ( EntityType ) uniqueKeyType ).getAssociatedEntityName();
uniqueKeyType = getFactory().getEntityPersister( className ).getIdentifierType();
}
return new EntityLoader( this, columns, uniqueKeyType, 1, LockMode.NONE, getFactory(), enabledFilters );
}
protected String getSQLWhereString(String alias) {
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
}
protected boolean hasWhere() {
return sqlWhereString != null;
}
private void initOrdinaryPropertyPaths(Mapping mapping) throws MappingException {
for ( int i = 0; i < getSubclassPropertyNameClosure().length; i++ ) {
propertyMapping.initPropertyPaths( getSubclassPropertyNameClosure()[i],
getSubclassPropertyTypeClosure()[i],
getSubclassPropertyColumnNameClosure()[i],
getSubclassPropertyFormulaTemplateClosure()[i],
mapping );
}
}
private void initIdentifierPropertyPaths(Mapping mapping) throws MappingException {
String idProp = getIdentifierPropertyName();
if ( idProp != null ) {
propertyMapping.initPropertyPaths( idProp, getIdentifierType(), getIdentifierColumnNames(), null, mapping );
}
if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
propertyMapping.initPropertyPaths( null, getIdentifierType(), getIdentifierColumnNames(), null, mapping );
}
propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getIdentifierColumnNames(), null, mapping );
}
private void initDiscriminatorPropertyPath(Mapping mapping) throws MappingException {
propertyMapping.initPropertyPaths( ENTITY_CLASS,
getDiscriminatorType(),
new String[]{getDiscriminatorColumnName()},
new String[]{getDiscriminatorFormulaTemplate()},
getFactory() );
}
protected void initPropertyPaths(Mapping mapping) throws MappingException {
initOrdinaryPropertyPaths(mapping);
initOrdinaryPropertyPaths(mapping); //do two passes, for collection property-ref!
initIdentifierPropertyPaths(mapping);
if ( entityMetamodel.isPolymorphic() ) initDiscriminatorPropertyPath(mapping);
}
protected UniqueEntityLoader createEntityLoader(LockMode lockMode, Map enabledFilters) throws MappingException {
//TODO: disable batch loading if lockMode > READ?
return BatchingEntityLoader.createBatchingEntityLoader( this, batchSize, lockMode, getFactory(), enabledFilters );
}
protected UniqueEntityLoader createEntityLoader(LockMode lockMode) throws MappingException {
return createEntityLoader( lockMode, CollectionHelper.EMPTY_MAP );
}
protected boolean check(int rows, Serializable id, int tableNumber) throws HibernateException {
if ( rows < 1 ) {
if ( !isNullableTable( tableNumber ) ) {
if ( getFactory().getStatistics().isStatisticsEnabled() ) {
getFactory().getStatisticsImplementor()
.optimisticFailure( getEntityName() );
}
throw new StaleObjectStateException( getEntityName(), id );
}
}
else if ( rows > 1 ) {
throw new HibernateException(
"Duplicate identifier in table for: " +
MessageHelper.infoString( this, id, getFactory() )
);
}
return rows > 0; //it could be zero if we have a "nullable" table
}
protected String generateUpdateString(boolean[] includeProperty, int j, boolean useRowId) {
return generateUpdateString( includeProperty, j, null, useRowId );
}
/**
* Generate the SQL that updates a row by id (and version)
*/
protected String generateUpdateString(final boolean[] includeProperty,
final int j,
final Object[] oldFields,
final boolean useRowId) {
Update update = new Update( getFactory().getDialect() ).setTableName( getTableName( j ) );
// select the correct row by either pk or rowid
if ( useRowId ) {
update.setPrimaryKeyColumnNames( new String[]{rowIdName} ); //TODO: eventually, rowIdName[j]
}
else {
update.setPrimaryKeyColumnNames( getKeyColumns( j ) );
}
boolean hasColumns = false;
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
// this is a property of the table, which we are updating
update.addColumns( getPropertyColumnNames(i), propertyColumnUpdateable[i] );
hasColumns = hasColumns || getPropertyColumnSpan( i ) > 0;
}
}
if ( j == 0 && isVersioned() && entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_VERSION ) {
// this is the root (versioned) table, and we are using version-based
// optimistic locking; if we are not updating the version, also don't
// check it (unless this is a "generated" version column)!
if ( checkVersion( includeProperty ) ) {
update.setVersionColumnName( getVersionColumnName() );
hasColumns = true;
}
}
else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION && oldFields != null ) {
// we are using "all" or "dirty" property-based optimistic locking
boolean[] includeInWhere = entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_ALL ?
getPropertyUpdateability() : //optimistic-lock="all", include all updatable properties
includeProperty; //optimistic-lock="dirty", include all properties we are updating this time
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
boolean[] versionability = getPropertyVersionability();
Type[] types = getPropertyTypes();
boolean include = includeInWhere[i] &&
isPropertyOfTable( i, j ) &&
versionability[i];
if ( include ) {
// this property belongs to the table, and it is not specifically
// excluded from optimistic locking by optimistic-lock="false"
String[] propertyColumnNames = getPropertyColumnNames( i );
boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() );
for ( int k=0; k<propertyNullness.length; k++ ) {
if ( propertyNullness[k] ) {
update.addWhereColumn( propertyColumnNames[k] );
}
else {
update.addWhereColumn( propertyColumnNames[k], " is null" );
}
}
}
}
}
if ( getFactory().getSettings().isCommentsEnabled() ) {
update.setComment( "update " + getEntityName() );
}
return hasColumns ? update.toStatementString() : null;
}
private boolean checkVersion(final boolean[] includeProperty) {
boolean checkVersion = includeProperty[ getVersionProperty() ] ||
entityMetamodel.getPropertyUpdateGeneration()[ getVersionProperty() ];
return checkVersion;
}
protected String generateInsertString(boolean[] includeProperty, int j) {
return generateInsertString( false, includeProperty, j );
}
protected String generateInsertString(boolean identityInsert, boolean[] includeProperty) {
return generateInsertString( identityInsert, includeProperty, 0 );
}
/**
* Generate the SQL that inserts a row
*/
protected String generateInsertString(boolean identityInsert, boolean[] includeProperty, int j) {
Insert insert = new Insert( getFactory().getDialect() )
.setTableName( getTableName( j ) );
// add normal properties
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
// this property belongs on the table and is to be inserted
insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i] );
}
}
// add the discriminator
if ( j == 0 ) addDiscriminatorToInsert( insert );
// add the primary key
if ( j == 0 && identityInsert ) {
insert.addIdentityColumn( getKeyColumns( 0 )[0] );
}
else {
insert.addColumns( getKeyColumns( j ) );
}
if ( getFactory().getSettings().isCommentsEnabled() ) {
insert.setComment( "insert " + getEntityName() );
}
String result = insert.toStatementString();
// append the SQL to return the generated identifier
if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { //TODO: suck into Insert
result = getFactory().getDialect().appendIdentitySelectToInsert( result );
}
return result;
}
/**
* Generate the SQL that deletes a row by id (and version)
*/
protected String generateDeleteString(int j) {
Delete delete = new Delete()
.setTableName( getTableName( j ) )
.setPrimaryKeyColumnNames( getKeyColumns( j ) );
if ( j == 0 ) delete.setVersionColumnName( getVersionColumnName() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
delete.setComment( "delete " + getEntityName() );
}
return delete.toStatementString();
}
protected int dehydrate(
Serializable id,
Object[] fields,
boolean[] includeProperty,
boolean[][] includeColumns,
int j,
PreparedStatement st,
SessionImplementor session)
throws HibernateException, SQLException {
return dehydrate( id, fields, null, includeProperty, includeColumns, j, st, session, 1 );
}
/**
* Marshall the fields of a persistent instance to a prepared statement
*/
protected int dehydrate(final Serializable id,
final Object[] fields,
final Object rowId,
final boolean[] includeProperty,
final boolean[][] includeColumns,
final int j,
final PreparedStatement ps,
final SessionImplementor session,
int index)
throws SQLException, HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "Dehydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) );
}
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
getPropertyTypes()[i].nullSafeSet( ps, fields[i], index, includeColumns[i], session );
//index += getPropertyColumnSpan( i );
index += ArrayHelper.countTrue( includeColumns[i] ); //TODO: this is kinda slow...
}
}
if ( rowId != null ) {
ps.setObject( index, rowId );
index += 1;
}
else if ( id != null ) {
getIdentifierType().nullSafeSet( ps, id, index, session );
index += getIdentifierColumnSpan();
}
return index;
}
/**
* Unmarshall the fields of a persistent instance from a result set,
* without resolving associations or collections. Question: should
* this really be here, or should it be sent back to Loader?
*/
public Object[] hydrate(final ResultSet rs,
final Serializable id,
final Object object,
final Loadable rootLoadable,
final String[][] suffixedPropertyColumns,
final boolean allProperties,
final SessionImplementor session)
throws SQLException, HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "Hydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) );
}
final AbstractEntityPersister rootPersister = (Abstrac
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -