📄 abstractentitypersister.java
字号:
} /** * Decide which tables need to be updated. * <p/> * The return here is an array of boolean values with each index corresponding * to a given table in the scope of this persister. * * @param dirtyProperties The indices of all the entity properties considered dirty. * @param hasDirtyCollection Whether any collections owned by the entity which were considered dirty. * * @return Array of booleans indicating which table require updating. */ protected boolean[] getTableUpdateNeeded(final int[] dirtyProperties, boolean hasDirtyCollection) { if ( dirtyProperties == null ) { return getTableHasColumns(); // for objects that came in via update() } else { boolean[] updateability = getPropertyUpdateability(); int[] propertyTableNumbers = getPropertyTableNumbers(); boolean[] tableUpdateNeeded = new boolean[ getTableSpan() ]; for ( int i = 0; i < dirtyProperties.length; i++ ) { int property = dirtyProperties[i]; int table = propertyTableNumbers[property]; tableUpdateNeeded[table] = tableUpdateNeeded[table] || ( getPropertyColumnSpan(property) > 0 && updateability[property] ); } if ( isVersioned() ) { tableUpdateNeeded[0] = tableUpdateNeeded[0] || Versioning.isVersionIncrementRequired( dirtyProperties, hasDirtyCollection, getPropertyVersionability() ); } return tableUpdateNeeded; } } public boolean hasRowId() { return rowIdName != null; } public AbstractEntityPersister( final PersistentClass persistentClass, final EntityRegionAccessStrategy cacheAccessStrategy, final SessionFactoryImplementor factory) throws HibernateException { // moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this.factory = factory; this.cacheAccessStrategy = cacheAccessStrategy; isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable(); this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ? (CacheEntryStructure) new StructuredCacheEntry(this) : (CacheEntryStructure) new UnstructuredCacheEntry(); this.entityMetamodel = new EntityMetamodel( persistentClass, factory ); if ( persistentClass.hasPojoRepresentation() ) { //TODO: this is currently specific to pojos, but need to be available for all entity-modes Iterator iter = persistentClass.getSubclassIterator(); while ( iter.hasNext() ) { PersistentClass pc = ( PersistentClass ) iter.next(); entityNameBySubclass.put( pc.getMappedClass(), pc.getEntityName() ); } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int batch = persistentClass.getBatchSize(); if ( batch == -1 ) { batch = factory.getSettings().getDefaultBatchFetchSize(); } batchSize = batch; hasSubselectLoadableCollections = persistentClass.hasSubselectLoadableCollections(); propertyMapping = new BasicEntityPropertyMapping( this ); // IDENTIFIER identifierColumnSpan = persistentClass.getIdentifier().getColumnSpan(); rootTableKeyColumnNames = new String[identifierColumnSpan]; identifierAliases = new String[identifierColumnSpan]; rowIdName = persistentClass.getRootTable().getRowId(); loaderName = persistentClass.getLoaderName(); Iterator iter = persistentClass.getIdentifier().getColumnIterator(); int i = 0; while ( iter.hasNext() ) { Column col = ( Column ) iter.next(); rootTableKeyColumnNames[i] = col.getQuotedName( factory.getDialect() ); identifierAliases[i] = col.getAlias( factory.getDialect(), persistentClass.getRootTable() ); i++; } // VERSION if ( persistentClass.isVersioned() ) { versionColumnName = ( ( Column ) persistentClass.getVersion().getColumnIterator().next() ).getQuotedName( factory.getDialect() ); } else { versionColumnName = null; } //WHERE STRING sqlWhereString = StringHelper.isNotEmpty( persistentClass.getWhere() ) ? "( " + persistentClass.getWhere() + ") " : null; sqlWhereStringTemplate = sqlWhereString == null ? null : Template.renderWhereStringTemplate( sqlWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() ); // PROPERTIES final boolean lazyAvailable = isInstrumented(EntityMode.POJO); int hydrateSpan = entityMetamodel.getPropertySpan(); propertyColumnSpans = new int[hydrateSpan]; propertySubclassNames = new String[hydrateSpan]; propertyColumnAliases = new String[hydrateSpan][]; propertyColumnNames = new String[hydrateSpan][]; propertyColumnFormulaTemplates = new String[hydrateSpan][]; propertyUniqueness = new boolean[hydrateSpan]; propertySelectable = new boolean[hydrateSpan]; propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][]; HashSet thisClassProperties = new HashSet(); lazyProperties = new HashSet(); ArrayList lazyNames = new ArrayList(); ArrayList lazyNumbers = new ArrayList(); ArrayList lazyTypes = new ArrayList(); ArrayList lazyColAliases = new ArrayList(); iter = persistentClass.getPropertyClosureIterator(); i = 0; boolean foundFormula = false; while ( iter.hasNext() ) { Property prop = ( Property ) iter.next(); thisClassProperties.add( prop ); int span = prop.getColumnSpan(); propertyColumnSpans[i] = span; propertySubclassNames[i] = prop.getPersistentClass().getEntityName(); String[] colNames = new String[span]; String[] colAliases = new String[span]; String[] templates = new String[span]; Iterator colIter = prop.getColumnIterator(); int k = 0; while ( colIter.hasNext() ) { Selectable thing = ( Selectable ) colIter.next(); colAliases[k] = thing.getAlias( factory.getDialect() , prop.getValue().getTable() ); if ( thing.isFormula() ) { foundFormula = true; templates[k] = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); } else { colNames[k] = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); } k++; } propertyColumnNames[i] = colNames; propertyColumnFormulaTemplates[i] = templates; propertyColumnAliases[i] = colAliases; if ( lazyAvailable && prop.isLazy() ) { lazyProperties.add( prop.getName() ); lazyNames.add( prop.getName() ); lazyNumbers.add( new Integer( i ) ); lazyTypes.add( prop.getValue().getType() ); lazyColAliases.add( colAliases ); } propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability(); propertyColumnInsertable[i] = prop.getValue().getColumnInsertability(); propertySelectable[i] = prop.isSelectable(); propertyUniqueness[i] = prop.getValue().isAlternateUniqueKey(); i++; } hasFormulaProperties = foundFormula; lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases ); lazyPropertyNames = ArrayHelper.toStringArray( lazyNames ); lazyPropertyNumbers = ArrayHelper.toIntArray( lazyNumbers ); lazyPropertyTypes = ArrayHelper.toTypeArray( lazyTypes ); // SUBCLASS PROPERTY CLOSURE ArrayList columns = new ArrayList(); ArrayList columnsLazy = new ArrayList(); ArrayList aliases = new ArrayList(); ArrayList formulas = new ArrayList(); ArrayList formulaAliases = new ArrayList(); ArrayList formulaTemplates = new ArrayList(); ArrayList formulasLazy = new ArrayList(); ArrayList types = new ArrayList(); ArrayList names = new ArrayList(); ArrayList classes = new ArrayList(); ArrayList templates = new ArrayList(); ArrayList propColumns = new ArrayList(); ArrayList joinedFetchesList = new ArrayList(); ArrayList cascades = new ArrayList(); ArrayList definedBySubclass = new ArrayList(); ArrayList propColumnNumbers = new ArrayList(); ArrayList propFormulaNumbers = new ArrayList(); ArrayList columnSelectables = new ArrayList(); ArrayList propNullables = new ArrayList(); iter = persistentClass.getSubclassPropertyClosureIterator(); while ( iter.hasNext() ) { Property prop = ( Property ) iter.next(); names.add( prop.getName() ); classes.add( prop.getPersistentClass().getEntityName() ); boolean isDefinedBySubclass = !thisClassProperties.contains( prop ); definedBySubclass.add( Boolean.valueOf( isDefinedBySubclass ) ); propNullables.add( Boolean.valueOf( prop.isOptional() || isDefinedBySubclass ) ); //TODO: is this completely correct? types.add( prop.getType() ); Iterator colIter = prop.getColumnIterator(); String[] cols = new String[prop.getColumnSpan()]; String[] forms = new String[prop.getColumnSpan()]; int[] colnos = new int[prop.getColumnSpan()]; int[] formnos = new int[prop.getColumnSpan()]; int l = 0; Boolean lazy = Boolean.valueOf( prop.isLazy() && lazyAvailable ); while ( colIter.hasNext() ) { Selectable thing = ( Selectable ) colIter.next(); if ( thing.isFormula() ) { String template = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); formnos[l] = formulaTemplates.size(); colnos[l] = -1; formulaTemplates.add( template ); forms[l] = template; formulas.add( thing.getText( factory.getDialect() ) ); formulaAliases.add( thing.getAlias( factory.getDialect() ) ); formulasLazy.add( lazy ); } else { String colName = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); colnos[l] = columns.size(); //before add :-) formnos[l] = -1; columns.add( colName ); cols[l] = colName; aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) ); columnsLazy.add( lazy ); columnSelectables.add( Boolean.valueOf( prop.isSelectable() ) ); } l++; } propColumns.add( cols ); templates.add( forms ); propColumnNumbers.add( colnos ); propFormulaNumbers.add( formnos ); joinedFetchesList.add( prop.getValue().getFetchMode() ); cascades.add( prop.getCascadeStyle() ); } subclassColumnClosure = ArrayHelper.toStringArray( columns ); subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases ); subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy ); subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables ); subclassFormulaClosure = ArrayHelper.toStringArray( formulas ); subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates ); subclassFormulaAliasClosure = ArrayHelper.toStringArray( formulaAliases ); subclassFormulaLazyClosure = ArrayHelper.toBooleanArray( formulasLazy ); subclassPropertyNameClosure = ArrayHelper.toStringArray( names ); subclassPropertySubclassNameClosure = ArrayHelper.toStringArray( classes ); subclassPropertyTypeClosure = ArrayHelper.toTypeArray( types ); subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables ); subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates ); subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns ); subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers ); subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers ); subclassPropertyCascadeStyleClosure = new CascadeStyle[cascades.size()]; iter = cascades.iterator(); int j = 0; while ( iter.hasNext() ) { subclassPropertyCascadeStyleClosure[j++] = ( CascadeStyle ) iter.next(); } subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.size()]; iter = joinedFetchesList.iterator(); j = 0; while ( iter.hasNext() ) { subclassPropertyFetchModeClosure[j++] = ( FetchMode ) iter.next(); } propertyDefinedOnSubclass = new boolean[definedBySubclass.size()]; iter = definedBySubclass.iterator(); j = 0; while ( iter.hasNext() ) { propertyDefinedOnSubclass[j++] = ( ( Boolean ) iter.next() ).booleanValue(); } // Handle any filters applied to the class level filterHelper = new FilterHelper( persistentClass.getFilterMap(), factory.getDialect(), factory.getSqlFunctionRegistry() ); temporaryIdTableName = persistentClass.getTemporaryIdTableName(); temporaryIdTableDDL = persistentClass.getTemporaryIdTableDDL(); } protected String generateLazySelectString() { if ( !entityMetamodel.hasLazyProperties() ) { return null; } HashSet tableNumbers = new HashSet(); ArrayList columnNumbers = new ArrayList(); ArrayList formulaNumbers = new ArrayList(); for ( int i = 0; i < lazyPropertyNames.length; i++ ) { // all this only really needs to consider properties // of this class, not its subclasses, but since we // are reusing code used for sequential selects, we // use the subclass closure int propertyNumber = getSubclassPropertyIndex( lazyPropertyNames[i] ); int tableNumber = getSubclassPropertyTableNumber( propertyNumber ); tableNumbers.add( new Integer( tableNumber ) ); int[] colNumbers = subclassPropertyColumnNumberClosure[propertyNumber]; for ( int j = 0; j < colNumbers.length; j++ ) { if ( colNumbers[j]!=-1 ) { columnNumbers.add( new Integer( colNumbers[j] ) ); } } int[] formNumbers = subclassPropertyFormulaNumberClosure[propertyNumber]; for ( int j = 0; j < formNumbers.length; j++ ) { if ( formNumbers[j]!=-1 ) { formulaNumbers.add( new Integer( formNumbers[j] ) ); } } } if ( columnNumbers.size()==0 && formulaNumbers.size()==0 ) { // only one-to-one is lazy fetched return null; } return renderSelect( ArrayHelper.toIntArray( tableNumbers ), ArrayHelper.toIntArray( columnNumbers ), ArrayHelper.toIntArray( formulaNumbers ) ); } public Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session) throws HibernateException { final Serializable id = session.getContextEntityIdentifier( entity ); final EntityEntry entry = session.getPersistenceContext().getEntry( entity ); if ( entry == null ) { throw new HibernateException( "entity is not associated with the session: " + id ); } if ( log.isTraceEnabled() ) { log.trace( "initializing lazy properties of: " + MessageHelper.infoString( this, id, getFactory() ) + ", field access: " + fieldName ); } if ( hasCache() ) { CacheKey cacheKey = new CacheKey(id, getIdentifierType(), getEntityName(), session.getEntityMode(), getFactory() ); Object ce = getCacheAccessStrategy().get( cacheKey, session.getTimestamp() ); if (ce!=null) { CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory); if ( !cacheEntry.areLazyPropertiesUnfetched() ) { //note early exit here: return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry ); } } } return initializeLazyPropertiesFromDatastore( fieldName, entity, session, id, entry ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -