1 package org.hibernate.persister.entity; 3 4 import java.io.Serializable ; 5 import java.sql.CallableStatement ; 6 import java.sql.PreparedStatement ; 7 import java.sql.ResultSet ; 8 import java.sql.SQLException ; 9 import java.sql.Types ; 10 import java.util.ArrayList ; 11 import java.util.Arrays ; 12 import java.util.HashMap ; 13 import java.util.HashSet ; 14 import java.util.Iterator ; 15 import java.util.Map ; 16 import java.util.Set ; 17 18 import net.sf.cglib.transform.impl.InterceptFieldEnabled; 19 20 import org.apache.commons.logging.Log; 21 import org.apache.commons.logging.LogFactory; 22 import org.hibernate.AssertionFailure; 23 import org.hibernate.EntityMode; 24 import org.hibernate.FetchMode; 25 import org.hibernate.HibernateException; 26 import org.hibernate.LockMode; 27 import org.hibernate.MappingException; 28 import org.hibernate.QueryException; 29 import org.hibernate.StaleObjectStateException; 30 import org.hibernate.cache.CacheConcurrencyStrategy; 31 import org.hibernate.cache.CacheKey; 32 import org.hibernate.cache.entry.CacheEntryStructure; 33 import org.hibernate.cache.entry.StructuredCacheEntry; 34 import org.hibernate.cache.entry.UnstructuredCacheEntry; 35 import org.hibernate.engine.CascadeStyle; 36 import org.hibernate.engine.EntityEntry; 37 import org.hibernate.engine.Mapping; 38 import org.hibernate.engine.SessionFactoryImplementor; 39 import org.hibernate.engine.SessionImplementor; 40 import org.hibernate.engine.Versioning; 41 import org.hibernate.exception.JDBCExceptionHelper; 42 import org.hibernate.id.IdentifierGenerator; 43 import org.hibernate.id.IdentifierGeneratorFactory; 44 import org.hibernate.id.PostInsertIdentifierGenerator; 45 import org.hibernate.id.PostInsertIdentityPersister; 46 import org.hibernate.intercept.FieldInterceptor; 47 import org.hibernate.intercept.LazyPropertyInitializer; 48 import org.hibernate.loader.entity.BatchingEntityLoader; 49 import org.hibernate.loader.entity.EntityLoader; 50 import org.hibernate.loader.entity.UniqueEntityLoader; 51 import org.hibernate.mapping.Column; 52 import org.hibernate.mapping.Component; 53 import org.hibernate.mapping.PersistentClass; 54 import org.hibernate.mapping.Property; 55 import org.hibernate.mapping.Selectable; 56 import org.hibernate.metadata.ClassMetadata; 57 import org.hibernate.pretty.MessageHelper; 58 import org.hibernate.property.BackrefPropertyAccessor; 59 import org.hibernate.sql.Alias; 60 import org.hibernate.sql.Delete; 61 import org.hibernate.sql.Insert; 62 import org.hibernate.sql.JoinFragment; 63 import org.hibernate.sql.Select; 64 import org.hibernate.sql.SelectFragment; 65 import org.hibernate.sql.SimpleSelect; 66 import org.hibernate.sql.Template; 67 import org.hibernate.sql.Update; 68 import org.hibernate.tuple.EntityMetamodel; 69 import org.hibernate.tuple.EntityTuplizer; 70 import org.hibernate.tuple.Tuplizer; 71 import org.hibernate.type.AbstractComponentType; 72 import org.hibernate.type.AssociationType; 73 import org.hibernate.type.EntityType; 74 import org.hibernate.type.Type; 75 import org.hibernate.type.TypeFactory; 76 import org.hibernate.type.VersionType; 77 import org.hibernate.util.ArrayHelper; 78 import org.hibernate.util.CollectionHelper; 79 import org.hibernate.util.FilterHelper; 80 import org.hibernate.util.GetGeneratedKeysHelper; 81 import org.hibernate.util.StringHelper; 82 83 89 public abstract class BasicEntityPersister 90 implements OuterJoinLoadable, Queryable, ClassMetadata, UniqueKeyLoadable, 91 SQLLoadable, LazyPropertyInitializer, PostInsertIdentityPersister { 92 93 private static final Log log = LogFactory.getLog( BasicEntityPersister.class ); 94 95 public static final String ENTITY_CLASS = "class"; 96 97 private final SessionFactoryImplementor factory; 99 private final CacheConcurrencyStrategy cache; 100 private final CacheEntryStructure cacheEntryStructure; 101 private final EntityMetamodel entityMetamodel; 102 private final Map entityNameBySubclass = new HashMap (); 103 105 private final String [] rootTableKeyColumnNames; 106 private final String [] identifierAliases; 107 private final int identifierColumnSpan; 108 private final String versionColumnName; 109 private final boolean hasFormulaProperties; 110 private final int batchSize; 111 private final boolean hasSubselectLoadableCollections; 112 protected final String rowIdName; 113 114 private final Set lazyProperties; 115 116 private final String sqlWhereString; 118 private final String sqlWhereStringTemplate; 119 120 private final int[] propertyColumnSpans; 124 private final String [] propertySubclassNames; 125 private final String [][] propertyColumnAliases; 126 private final String [][] propertyColumnNames; 127 private final String [][] propertyColumnFormulaTemplates; 128 private final boolean[][] propertyColumnUpdateable; 129 private final boolean[][] propertyColumnInsertable; 130 private final boolean[] propertyUniqueness; 131 private final boolean[] propertySelectable; 132 133 private final String [] lazyPropertyNames; 135 private final int[] lazyPropertyNumbers; 136 private final Type[] lazyPropertyTypes; 137 private final String [][] lazyPropertyColumnAliases; 138 139 private final String [] subclassPropertyNameClosure; 141 private final String [] subclassPropertySubclassNameClosure; 142 private final Type[] subclassPropertyTypeClosure; 143 private final String [][] subclassPropertyFormulaTemplateClosure; 144 private final String [][] subclassPropertyColumnNameClosure; 145 private final FetchMode[] subclassPropertyFetchModeClosure; 146 private final boolean[] subclassPropertyNullabilityClosure; 147 private final boolean[] propertyDefinedOnSubclass; 148 private final int[][] subclassPropertyColumnNumberClosure; 149 private final int[][] subclassPropertyFormulaNumberClosure; 150 151 private final String [] subclassColumnClosure; 153 private final boolean[] subclassColumnLazyClosure; 154 private final String [] subclassColumnAliasClosure; 155 private final boolean[] subclassColumnSelectableClosure; 156 private final String [] subclassFormulaClosure; 157 private final String [] subclassFormulaTemplateClosure; 158 private final String [] subclassFormulaAliasClosure; 159 private final boolean[] subclassFormulaLazyClosure; 160 161 private final FilterHelper filterHelper; 163 164 private final Map uniqueKeyLoaders = new HashMap (); 165 private final Map lockers = new HashMap (); 166 private final Map loaders = new HashMap (); 167 168 private String sqlVersionSelectString; 170 private String sqlSnapshotSelectString; 171 private String sqlLazySelectString; 172 173 private String sqlIdentityInsertString; 174 private String sqlUpdateByRowIdString; 175 private String sqlLazyUpdateByRowIdString; 176 177 private String [] sqlDeleteStrings; 178 private String [] sqlInsertStrings; 179 private String [] sqlUpdateStrings; 180 private String [] sqlLazyUpdateStrings; 181 182 protected boolean[] insertCallable; 184 protected boolean[] updateCallable; 185 protected boolean[] deleteCallable; 186 protected String [] customSQLInsert; 187 protected String [] customSQLUpdate; 188 protected String [] customSQLDelete; 189 190 private boolean[] tableHasColumns; 191 192 private final String loaderName; 193 194 private UniqueEntityLoader queryLoader; 195 196 private final String temporaryIdTableName; 197 private final String temporaryIdTableDDL; 198 199 private final Map subclassPropertyAliases = new HashMap (); 200 private final Map subclassPropertyColumnNames = new HashMap (); 201 202 protected final BasicEntityPropertyMapping propertyMapping; 203 204 protected void addDiscriminatorToInsert(Insert insert) {} 205 206 protected void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {} 207 208 protected abstract int[] getSubclassColumnTableNumberClosure(); 209 210 protected abstract int[] getSubclassFormulaTableNumberClosure(); 211 212 public abstract String getSubclassTableName(int j); 213 214 protected abstract String [] getSubclassTableKeyColumns(int j); 215 216 protected abstract boolean isClassOrSuperclassTable(int j); 217 218 protected abstract int getSubclassTableSpan(); 219 220 protected abstract int getTableSpan(); 221 222 protected abstract boolean isTableCascadeDeleteEnabled(int j); 223 224 protected abstract String getTableName(int j); 225 226 protected abstract String [] getKeyColumns(int j); 227 228 protected abstract boolean isPropertyOfTable(int property, int j); 229 230 protected abstract int[] getPropertyTableNumbersInSelect(); 231 232 protected abstract int[] getPropertyTableNumbers(); 233 234 protected abstract int getSubclassPropertyTableNumber(int i); 235 236 protected abstract String filterFragment(String alias) throws MappingException; 237 238 private static final String DISCRIMINATOR_ALIAS = "clazz_"; 239 240 public String getDiscriminatorColumnName() { 241 return DISCRIMINATOR_ALIAS; 242 } 243 244 protected String getDiscriminatorAlias() { 245 return DISCRIMINATOR_ALIAS; 246 } 247 248 protected String getDiscriminatorFormulaTemplate() { 249 return null; 250 } 251 252 protected boolean isInverseTable(int j) { 253 return false; 254 } 255 256 protected boolean isNullableTable(int j) { 257 return false; 258 } 259 260 protected boolean isNullableSubclassTable(int j) { 261 return false; 262 } 263 264 protected boolean isInverseSubclassTable(int j) { 265 return false; 266 } 267 268 public boolean isSubclassEntityName(String entityName) { 269 return entityMetamodel.getSubclassEntityNames().contains(entityName); 270 } 271 272 private boolean[] getTableHasColumns() { 273 return tableHasColumns; 274 } 275 276 public String [] getRootTableKeyColumnNames() { 277 return rootTableKeyColumnNames; 278 } 279 280 protected String [] getSQLUpdateByRowIdStrings() { 281 if ( sqlUpdateByRowIdString == null ) { 282 throw new AssertionFailure( "no update by row id" ); 283 } 284 String [] result = new String [getTableSpan()]; 285 result[0] = sqlUpdateByRowIdString; 286 for ( int i = 1; i < getTableSpan(); i++ ) result[i] = sqlUpdateStrings[i]; 287 return result; 288 } 289 290 protected String [] getSQLLazyUpdateByRowIdStrings() { 291 if ( sqlLazyUpdateByRowIdString == null ) { 292 throw new AssertionFailure( "no update by row id" ); 293 } 294 String [] result = new String [getTableSpan()]; 295 result[0] = sqlLazyUpdateByRowIdString; 296 for ( int i = 1; i < getTableSpan(); i++ ) result[i] = sqlLazyUpdateStrings[i]; 297 return result; 298 } 299 300 protected String getSQLSnapshotSelectString() { 301 return sqlSnapshotSelectString; 302 } 303 304 protected String getSQLLazySelectString() { 305 return sqlLazySelectString; 306 } 307 308 protected String [] getSQLDeleteStrings() { 309 return sqlDeleteStrings; 310 } 311 312 protected String [] getSQLInsertStrings() { 313 return sqlInsertStrings; 314 } 315 316 protected String [] getSQLUpdateStrings() { 317 return sqlUpdateStrings; 318 } 319 320 protected String [] getSQLLazyUpdateStrings() { 321 return sqlLazyUpdateStrings; 322 } 323 324 327 protected String getSQLIdentityInsertString() { 328 return sqlIdentityInsertString; 329 } 330 331 protected String getVersionSelectString() { 332 return sqlVersionSelectString; 333 } 334 335 protected boolean isInsertCallable(int j) { 336 return insertCallable[j]; 337 } 338 339 protected boolean isUpdateCallable(int j) { 340 return updateCallable[j]; 341 } 342 343 protected boolean isDeleteCallable(int j) { 344 return deleteCallable[j]; 345 } 346 347 protected boolean isSubclassPropertyDeferred(String propertyName, String entityName) { 348 return false; 349 } 350 351 protected boolean isSubclassTableSequentialSelect(int j) { 352 return false; 353 } 354 355 public boolean hasSequentialSelect() { 356 return false; 357 } 358 359 362 protected boolean[] getTableUpdateNeeded(final int[] dirtyProperties, boolean hasDirtyCollection) { 363 364 if ( dirtyProperties == null ) { 365 return getTableHasColumns(); } 367 else { 368 boolean[] updateability = getPropertyUpdateability(); 369 int[] propertyTableNumbers = getPropertyTableNumbers(); 370 boolean[] tableUpdateNeeded = new boolean[ getTableSpan() ]; 371 for ( int i = 0; i < dirtyProperties.length; i++ ) { 372 int property = dirtyProperties[i]; 373 int table = propertyTableNumbers[property]; 374 tableUpdateNeeded[table] = tableUpdateNeeded[table] || 375 ( getPropertyColumnSpan(property) > 0 && updateability[property] ); 376 } 377 if ( isVersioned() ) { 378 tableUpdateNeeded[0] = tableUpdateNeeded[0] || 379 Versioning.isVersionIncrementRequired( dirtyProperties, hasDirtyCollection, getPropertyVersionability() ); 380 } 381 return tableUpdateNeeded; 382 } 383 } 384 385 public boolean hasRowId() { 386 return rowIdName != null; 387 } 388 389 public BasicEntityPersister( 390 final PersistentClass persistentClass, 391 final CacheConcurrencyStrategy cache, 392 final SessionFactoryImplementor factory) 393 throws HibernateException { 394 395 this.factory = factory; 397 this.cache = cache; 398 this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ? 399 (CacheEntryStructure) new StructuredCacheEntry(this) : 400 (CacheEntryStructure) new UnstructuredCacheEntry(); 401 402 this.entityMetamodel = new EntityMetamodel( persistentClass, factory ); 403 404 if ( persistentClass.hasPojoRepresentation() ) { 405 Iterator iter = persistentClass.getSubclassIterator(); 407 while ( iter.hasNext() ) { 408 PersistentClass pc = ( PersistentClass ) iter.next(); 409 entityNameBySubclass.put( pc.getMappedClass(), pc.getEntityName() ); 410 } 411 } 412 414 int batch = persistentClass.getBatchSize(); 415 if (batch==-1) batch = factory.getSettings().getDefaultBatchFetchSize(); 416 batchSize = batch; 417 hasSubselectLoadableCollections = persistentClass.hasSubselectLoadableCollections(); 418 419 propertyMapping = new BasicEntityPropertyMapping( this ); 420 421 423 identifierColumnSpan = persistentClass.getIdentifier().getColumnSpan(); 424 rootTableKeyColumnNames = new String [identifierColumnSpan]; 425 identifierAliases = new String [identifierColumnSpan]; 426 427 rowIdName = persistentClass.getRootTable().getRowId(); 428 429 loaderName = persistentClass.getLoaderName(); 430 431 Iterator iter = persistentClass.getIdentifier().getColumnIterator(); 432 int i = 0; 433 while ( iter.hasNext() ) { 434 Column col = ( Column ) iter.next(); 435 rootTableKeyColumnNames[i] = col.getQuotedName( factory.getDialect() ); 436 identifierAliases[i] = col.getAlias( factory.getDialect(), persistentClass.getRootTable() ); 437 i++; 438 } 439 440 442 if ( persistentClass.isVersioned() ) { 443 versionColumnName = ( ( Column ) persistentClass.getVersion().getColumnIterator().next() ).getQuotedName( factory.getDialect() ); 444 } 445 else { 446 versionColumnName = null; 447 } 448 449 451 sqlWhereString = persistentClass.getWhere(); 452 sqlWhereStringTemplate = sqlWhereString == null ? 453 null : 454 Template.renderWhereStringTemplate( sqlWhereString, factory.getDialect() ); 455 456 458 final boolean lazyAvailable = isInstrumented(EntityMode.POJO); 459 460 int hydrateSpan = entityMetamodel.getPropertySpan(); 461 propertyColumnSpans = new int[hydrateSpan]; 462 propertySubclassNames = new String [hydrateSpan]; 463 propertyColumnAliases = new String [hydrateSpan][]; 464 propertyColumnNames = new String [hydrateSpan][]; 465 propertyColumnFormulaTemplates = new String [hydrateSpan][]; 466 propertyUniqueness = new boolean[hydrateSpan]; 467 propertySelectable = new boolean[hydrateSpan]; 468 propertyColumnUpdateable = new boolean[hydrateSpan][]; 469 propertyColumnInsertable = new boolean[hydrateSpan][]; 470 HashSet thisClassProperties = new HashSet (); 471 472 lazyProperties = new HashSet (); 473 ArrayList lazyNames = new ArrayList (); 474 ArrayList lazyNumbers = new ArrayList (); 475 ArrayList lazyTypes = new ArrayList (); 476 ArrayList lazyColAliases = new ArrayList (); 477 478 iter = persistentClass.getPropertyClosureIterator(); 479 i = 0; 480 boolean foundFormula = false; 481 while ( iter.hasNext() ) { 482 Property prop = ( Property ) iter.next(); 483 thisClassProperties.add( prop ); 484 485 int span = prop.getColumnSpan(); 486 propertyColumnSpans[i] = span; 487 propertySubclassNames[i] = prop.getPersistentClass().getEntityName(); 488 String [] colNames = new String [span]; 489 String [] colAliases = new String [span]; 490 String [] templates = new String [span]; 491 Iterator colIter = prop.getColumnIterator(); 492 int k = 0; 493 while ( colIter.hasNext() ) { 494 Selectable thing = ( Selectable ) colIter.next(); 495 colAliases[k] = thing.getAlias( factory.getDialect() , prop.getValue().getTable() ); 496 if ( thing.isFormula() ) { 497 foundFormula = true; 498 templates[k] = thing.getTemplate( factory.getDialect() ); 499 } 500 else { 501 colNames[k] = thing.getTemplate( factory.getDialect() ); 502 } 503 k++; 504 } 505 propertyColumnNames[i] = colNames; 506 propertyColumnFormulaTemplates[i] = templates; 507 propertyColumnAliases[i] = colAliases; 508 509 if ( lazyAvailable && prop.isLazy() ) { 510 lazyProperties.add( prop.getName() ); 511 lazyNames.add( prop.getName() ); 512 lazyNumbers.add( new Integer ( i ) ); 513 lazyTypes.add( prop.getValue().getType() ); 514 lazyColAliases.add( colAliases ); 515 } 516 517 propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability(); 518 propertyColumnInsertable[i] = prop.getValue().getColumnInsertability(); 519 520 propertySelectable[i] = prop.isSelectable(); 521 522 propertyUniqueness[i] = prop.getValue().isAlternateUniqueKey(); 523 524 i++; 525 526 } 527 hasFormulaProperties = foundFormula; 528 lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases ); 529 lazyPropertyNames = ArrayHelper.toStringArray( lazyNames ); 530 lazyPropertyNumbers = ArrayHelper.toIntArray( lazyNumbers ); 531 lazyPropertyTypes = ArrayHelper.toTypeArray( lazyTypes ); 532 533 535 ArrayList columns = new ArrayList (); 536 ArrayList columnsLazy = new ArrayList (); 537 ArrayList aliases = new ArrayList (); 538 ArrayList formulas = new ArrayList (); 539 ArrayList formulaAliases = new ArrayList (); 540 ArrayList formulaTemplates = new ArrayList (); 541 ArrayList formulasLazy = new ArrayList (); 542 ArrayList types = new ArrayList (); 543 ArrayList names = new ArrayList (); 544 ArrayList classes = new ArrayList (); 545 ArrayList templates = new ArrayList (); 546 ArrayList propColumns = new ArrayList (); 547 ArrayList joinedFetchesList = new ArrayList (); 548 ArrayList definedBySubclass = new ArrayList (); 549 ArrayList propColumnNumbers = new ArrayList (); 550 ArrayList propFormulaNumbers = new ArrayList (); 551 ArrayList columnSelectables = new ArrayList (); 552 ArrayList propNullables = new ArrayList (); 553 554 iter = persistentClass.getSubclassPropertyClosureIterator(); 555 while ( iter.hasNext() ) { 556 Property prop = ( Property ) iter.next(); 557 names.add( prop.getName() ); 558 classes.add( prop.getPersistentClass().getEntityName() ); 559 boolean isDefinedBySubclass = !thisClassProperties.contains( prop ); 560 definedBySubclass.add( new Boolean (isDefinedBySubclass) ); 561 propNullables.add( new Boolean ( prop.isOptional() || isDefinedBySubclass) ); types.add( prop.getType() ); 563 564 Iterator colIter = prop.getColumnIterator(); 565 String [] cols = new String [prop.getColumnSpan()]; 566 String [] forms = new String [prop.getColumnSpan()]; 567 int[] colnos = new int[prop.getColumnSpan()]; 568 int[] formnos = new int[prop.getColumnSpan()]; 569 int l = 0; 570 Boolean lazy = new Boolean ( prop.isLazy() && lazyAvailable ); 571 while ( colIter.hasNext() ) { 572 Selectable thing = ( Selectable ) colIter.next(); 573 if ( thing.isFormula() ) { 574 String template = thing.getTemplate( factory.getDialect() ); 575 formnos[l] = formulaTemplates.size(); 576 colnos[l] = -1; 577 formulaTemplates.add( template ); 578 forms[l] = template; 579 formulas.add( thing.getText( factory.getDialect() ) ); 580 formulaAliases.add( thing.getAlias( factory.getDialect() ) ); 581 formulasLazy.add( lazy ); 582 } 583 else { 584 String colName = thing.getTemplate( factory.getDialect() ); 585 colnos[l] = columns.size(); formnos[l] = -1; 587 columns.add( colName ); 588 cols[l] = colName; 589 aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) ); 590 columnsLazy.add( lazy ); 591 columnSelectables.add( new Boolean ( prop.isSelectable() ) ); 592 } 593 l++; 594 } 595 propColumns.add( cols ); 596 templates.add( forms ); 597 propColumnNumbers.add( colnos ); 598 propFormulaNumbers.add( formnos ); 599 600 joinedFetchesList.add( prop.getValue().getFetchMode() ); 601 } 602 subclassColumnClosure = ArrayHelper.toStringArray( columns ); 603 subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases ); 604 subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy ); 605 subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables ); 606 607 subclassFormulaClosure = ArrayHelper.toStringArray( formulas ); 608 subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates ); 609 subclassFormulaAliasClosure = ArrayHelper.toStringArray( formulaAliases ); 610 subclassFormulaLazyClosure = ArrayHelper.toBooleanArray( formulasLazy ); 611 612 subclassPropertyNameClosure = ArrayHelper.toStringArray( names ); 613 subclassPropertySubclassNameClosure = ArrayHelper.toStringArray( classes ); 614 subclassPropertyTypeClosure = ArrayHelper.toTypeArray( types ); 615 subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables ); 616 subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates ); 617 subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns ); 618 subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers ); 619 subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers ); 620 621 subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.size()]; 622 iter = joinedFetchesList.iterator(); 623 int j = 0; 624 while ( iter.hasNext() ) subclassPropertyFetchModeClosure[j++] = ( FetchMode ) iter.next(); 625 626 propertyDefinedOnSubclass = new boolean[definedBySubclass.size()]; 627 iter = definedBySubclass.iterator(); 628 j = 0; 629 while ( iter.hasNext() ) propertyDefinedOnSubclass[j++] = ( ( Boolean ) iter.next() ).booleanValue(); 630 631 filterHelper = new FilterHelper( persistentClass.getFilterMap(), factory.getDialect() ); 633 634 temporaryIdTableName = persistentClass.getTemporaryIdTableName(); 635 temporaryIdTableDDL = persistentClass.getTemporaryIdTableDDL(); 636 } 637 638 protected String generateLazySelectString() { 639 640 if ( !entityMetamodel.hasLazyProperties() ) return null; 641 642 HashSet tableNumbers = new HashSet (); 643 ArrayList columnNumbers = new ArrayList (); 644 ArrayList formulaNumbers = new ArrayList (); 645 for ( int i = 0; i < lazyPropertyNames.length; i++ ) { 646 int propertyNumber = getSubclassPropertyIndex( lazyPropertyNames[i] ); 651 652 int tableNumber = getSubclassPropertyTableNumber( propertyNumber ); 653 tableNumbers.add( new Integer ( tableNumber ) ); 654 655 int[] colNumbers = subclassPropertyColumnNumberClosure[propertyNumber]; 656 for ( int j = 0; j < colNumbers.length; j++ ) { 657 if ( colNumbers[j]!=-1 ) { 658 columnNumbers.add( new Integer ( colNumbers[j] ) ); 659 } 660 } 661 int[] formNumbers = subclassPropertyFormulaNumberClosure[propertyNumber]; 662 for ( int j = 0; j < formNumbers.length; j++ ) { 663 if ( formNumbers[j]!=-1 ) { 664 formulaNumbers.add( new Integer ( formNumbers[j] ) ); 665 } 666 } 667 } 668 669 if ( columnNumbers.size()==0 && formulaNumbers.size()==0 ) { 670 return null; 672 } 673 674 return renderSelect( ArrayHelper.toIntArray( tableNumbers ), 675 ArrayHelper.toIntArray( columnNumbers ), 676 ArrayHelper.toIntArray( formulaNumbers ) ); 677 678 } 679 680 public Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session) 681 throws HibernateException { 682 683 final Serializable id = session.getContextEntityIdentifier( entity ); 684 685 final EntityEntry entry = session.getPersistenceContext().getEntry( entity ); 686 if ( entry == null ) throw new HibernateException( "entity is not associated with the session: " + id ); 687 688 if ( log.isTraceEnabled() ) { 689 log.trace( "initializing lazy properties of: " + 690 MessageHelper.infoString( this, id, getFactory() ) + 691 ", field access: " + fieldName ); 692 } 693 694 try { 695 696 Object result = null; 697 PreparedStatement ps = null; 698 ResultSet rs = null; 699 try { 700 final String lazySelect = getSQLLazySelectString(); 701 if (lazySelect!=null) { 702 ps = session.getBatcher().prepareSelectStatement(lazySelect); 705 getIdentifierType().nullSafeSet( ps, id, 1, session ); 706 rs = ps.executeQuery(); 707 rs.next(); 708 } 709 final Object [] snapshot = entry.getLoadedState(); 710 for ( int j = 0; j < lazyPropertyNames.length; j++ ) { 711 Object propValue = lazyPropertyTypes[j].nullSafeGet( rs, lazyPropertyColumnAliases[j], session, entity ); 712 setPropertyValue( entity, lazyPropertyNumbers[j], propValue, session.getEntityMode() ); 713 snapshot[ lazyPropertyNumbers[j] ] = lazyPropertyTypes[j].deepCopy( propValue, session.getEntityMode(), factory ); 714 if ( fieldName.equals( lazyPropertyNames[j] ) ) result = propValue; 715 } 716 if (rs!=null) rs.close(); 717 } 718 finally { 719 if (ps!=null) session.getBatcher().closeStatement(ps); 720 } 721 722 log.trace( "done initializing lazy properties" ); 723 724 return result; 725 726 } 727 catch ( SQLException sqle ) { 728 throw JDBCExceptionHelper.convert( 729 getFactory().getSQLExceptionConverter(), 730 sqle, 731 "could not initialize lazy properties: " + 732 MessageHelper.infoString( this, id, getFactory() ), 733 getSQLLazySelectString() 734 ); 735 } 736 737 } 738 739 public boolean isBatchable() { 740 return optimisticLockMode()==Versioning.OPTIMISTIC_LOCK_NONE || 741 ( !isVersioned() && optimisticLockMode()==Versioning.OPTIMISTIC_LOCK_VERSION ) || 742 getFactory().getSettings().isJdbcBatchVersionedData(); 743 } 744 745 public Serializable [] getQuerySpaces() { 746 return getPropertySpaces(); 747 } 748 749 protected Set getLazyProperties() { 750 return lazyProperties; 751 } 752 753 private String getLockString(LockMode lockMode) { 754 return ( String ) lockers.get( lockMode ); 755 } 756 757 public boolean isBatchLoadable() { 758 return batchSize > 1; 759 } 760 761 public String [] getIdentifierColumnNames() { 762 return rootTableKeyColumnNames; 763 } 764 765 protected int getIdentifierColumnSpan() { 766 return identifierColumnSpan; 767 } 768 769 protected String [] getIdentifierAliases() { 770 return identifierAliases; 771 } 772 773 public String getVersionColumnName() { 774 return versionColumnName; 775 } 776 777 protected String getVersionedTableName() { 778 return getTableName( 0 ); 779 } 780 781 protected boolean[] getSubclassColumnLazyiness() { 782 return subclassColumnLazyClosure; 783 } 784 785 protected boolean[] getSubclassFormulaLazyiness() { 786 return subclassFormulaLazyClosure; 787 } 788 789 798 public boolean isCacheInvalidationRequired() { 799 return hasFormulaProperties() || 800 ( !isVersioned() && ( entityMetamodel.isDynamicUpdate() || getTableSpan() > 1 ) ); 801 } 802 803 public String selectFragment(String alias, String suffix) { 804 return identifierSelectFragment( alias, suffix ) + 805 propertySelectFragment( alias, suffix, false ); 806 } 807 808 public String [] getIdentifierAliases(String suffix) { 809 return new Alias( suffix ).toAliasStrings( getIdentifierAliases() ); 813 } 814 815 public String [] getPropertyAliases(String suffix, int i) { 816 return new Alias( suffix ).toUnquotedAliasStrings( propertyColumnAliases[i] ); 818 } 819 820 public String getDiscriminatorAlias(String suffix) { 821 return entityMetamodel.hasSubclasses() ? 825 new Alias( suffix ).toAliasString( getDiscriminatorAlias() ) : 826 null; 827 } 828 829 public String identifierSelectFragment(String name, String suffix) { 830 return new SelectFragment() 831 .setSuffix( suffix ) 832 .addColumns( name, getIdentifierColumnNames(), getIdentifierAliases() ) 833 .toFragmentString() 834 .substring( 2 ); } 836 837 838 public String propertySelectFragment(String name, String suffix, boolean allProperties) { 839 840 SelectFragment select = new SelectFragment() 841 .setSuffix( suffix ) 842 .setUsedAliases( getIdentifierAliases() ); 843 844 int[] columnTableNumbers = getSubclassColumnTableNumberClosure(); 845 String [] columnAliases = getSubclassColumnAliasClosure(); 846 String [] columns = getSubclassColumnClosure(); 847 for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) { 848 boolean selectable = ( allProperties || !subclassColumnLazyClosure[i] ) && 849 !isSubclassTableSequentialSelect( columnTableNumbers[i] ) && 850 subclassColumnSelectableClosure[i]; 851 if ( selectable ) { 852 String subalias = generateTableAlias( name, columnTableNumbers[i] ); 853 select.addColumn( subalias, columns[i], columnAliases[i] ); 854 } 855 } 856 857 int[] formulaTableNumbers = getSubclassFormulaTableNumberClosure(); 858 String [] formulaTemplates = getSubclassFormulaTemplateClosure(); 859 String [] formulaAliases = getSubclassFormulaAliasClosure(); 860 for ( int i = 0; i < getSubclassFormulaTemplateClosure().length; i++ ) { 861 boolean selectable = ( allProperties || !subclassFormulaLazyClosure[i] ) 862 && !isSubclassTableSequentialSelect( formulaTableNumbers[i] ); 863 if ( selectable ) { 864 String subalias = generateTableAlias( name, formulaTableNumbers[i] ); 865 select.addFormula( subalias, formulaTemplates[i], formulaAliases[i] ); 866 } 867 } 868 869 if ( entityMetamodel.hasSubclasses() ) addDiscriminatorToSelect( select, name, suffix ); 870 871 if ( hasRowId() ) select.addColumn( name, rowIdName, ROWID_ALIAS ); 872 873 return select.toFragmentString(); 874 } 875 876 public Object [] getDatabaseSnapshot(Serializable id, SessionImplementor session) 877 throws HibernateException { 878 879 if ( log.isTraceEnabled() ) { 880 log.trace( "Getting current persistent state for: " + MessageHelper.infoString( this, id, getFactory() ) ); 881 } 882 883 try { 884 PreparedStatement ps = session.getBatcher().prepareSelectStatement( getSQLSnapshotSelectString() ); 885 try { 886 getIdentifierType().nullSafeSet( ps, id, 1, session ); 887 ResultSet rs = ps.executeQuery(); 889 try { 890 if ( !rs.next() ) return null; 892 893 Type[] types = getPropertyTypes(); 895 Object [] values = new Object [types.length]; 896 boolean[] includeProperty = getPropertyUpdateability(); 897 for ( int i = 0; i < types.length; i++ ) { 898 if ( includeProperty[i] ) { 899 values[i] = types[i].hydrate( rs, getPropertyAliases( "", i ), session, null ); } 901 } 902 return values; 903 } 904 finally { 905 rs.close(); 906 } 907 } 908 finally { 909 session.getBatcher().closeStatement( ps ); 910 } 911 } 912 catch ( SQLException sqle ) { 913 throw JDBCExceptionHelper.convert( 914 getFactory().getSQLExceptionConverter(), 915 sqle, 916 "could not retrieve snapshot: " + 917 MessageHelper.infoString( this, id, getFactory() ), 918 getSQLSnapshotSelectString() 919 ); 920 } 921 922 } 923 924 927 protected String generateSelectVersionString() { 928 SimpleSelect select = new SimpleSelect( getFactory().getDialect() ) 929 .setTableName( getVersionedTableName() ); 930 if ( isVersioned() ) { 931 select.addColumn( versionColumnName ); 932 } 933 else { 934 select.addColumns( rootTableKeyColumnNames ); 935 } 936 if ( getFactory().getSettings().isCommentsEnabled() ) { 937 select.setComment( "get version " + getEntityName() ); 938 } 939 return select.addCondition( rootTableKeyColumnNames, "=?" ).toStatementString(); 940 } 941 942 protected String concretePropertySelectFragment(String alias, boolean[] includeProperty) { 943 int propertyCount = getPropertyNames().length; 944 int[] propertyTableNumbers = getPropertyTableNumbersInSelect(); 945 SelectFragment frag = new SelectFragment(); 946 for ( int i = 0; i < propertyCount; i++ ) { 947 if ( includeProperty[i] ) { frag.addColumns( 949 generateTableAlias( alias, propertyTableNumbers[i] ), 950 propertyColumnNames[i], 951 propertyColumnAliases[i] 952 ); 953 frag.addFormulas( 954 generateTableAlias( alias, propertyTableNumbers[i] ), 955 propertyColumnFormulaTemplates[i], 956 propertyColumnAliases[i] 957 ); 958 } 959 } 960 return frag.toFragmentString(); 961 } 962 963 protected String generateSnapshotSelectString() { 964 965 967 Select select = new Select( getFactory().getDialect() ); 968 969 if ( getFactory().getSettings().isCommentsEnabled() ) { 970 select.setComment( "get current state " + getEntityName() ); 971 } 972 973 String [] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() ); 974 String selectClause = StringHelper.join( ", ", aliasedIdColumns ) + 975 concretePropertySelectFragment( getRootAlias(), getPropertyUpdateability() ); 976 977 String fromClause = fromTableFragment( getRootAlias() ) + 978 fromJoinFragment( getRootAlias(), true, false ); 979 980 String whereClause = new StringBuffer () 981 .append( StringHelper.join( "=? and ", 982 aliasedIdColumns ) ) 983 .append( "=?" ) 984 .append( whereJoinFragment( getRootAlias(), true, false ) ) 985 .toString(); 986 987 992 993 return select.setSelectClause( selectClause ) 994 .setFromClause( fromClause ) 995 .setOuterJoins( "", "" ) 996 .setWhereClause( whereClause ) 997 .toStatementString(); 998 } 999 1000 1003 public void lock(Serializable id, Object version, Object object, LockMode lockMode, SessionImplementor session) 1004 throws HibernateException { 1005 1006 if ( lockMode != LockMode.NONE ) { 1007 1008 if ( log.isTraceEnabled() ) { 1009 log.trace( "Locking entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 1010 if ( isVersioned() ) log.trace( "Version: " + version ); 1011 } 1012 1013 final String sql = getLockString( lockMode ); 1014 1015 try { 1016 1017 PreparedStatement st = session.getBatcher().prepareSelectStatement( sql ); 1018 try { 1019 getIdentifierType().nullSafeSet( st, id, 1, session ); 1020 if ( isVersioned() ) { 1021 getVersionType().nullSafeSet( st, version, getIdentifierColumnSpan() + 1, session ); 1022 } 1023 1024 ResultSet rs = st.executeQuery(); 1025 try { 1026 if ( !rs.next() ) { 1027 throw new StaleObjectStateException( getEntityName(), id ); 1028 } 1029 } 1030 finally { 1031 rs.close(); 1032 } 1033 } 1034 finally { 1035 session.getBatcher().closeStatement( st ); 1036 } 1037 1038 } 1039 catch ( SQLException sqle ) { 1040 throw JDBCExceptionHelper.convert( 1041 getFactory().getSQLExceptionConverter(), 1042 sqle, 1043 "could not lock: " + 1044 MessageHelper.infoString( this, id, getFactory() ), 1045 sql 1046 ); 1047 } 1048 1049 } 1050 1051 } 1052 1053 1056 public Object getCurrentVersion(Serializable id, SessionImplementor session) throws HibernateException { 1057 1058 if ( log.isTraceEnabled() ) { 1059 log.trace( "Getting version: " + MessageHelper.infoString( this, id, getFactory() ) ); 1060 } 1061 1062 try { 1063 1064 PreparedStatement st = session.getBatcher().prepareSelectStatement( getVersionSelectString() ); 1065 try { 1066 getIdentifierType().nullSafeSet( st, id, 1, session ); 1067 1068 ResultSet rs = st.executeQuery(); 1069 try { 1070 if ( !rs.next() ) return null; 1071 if ( !isVersioned() ) return this; 1072 return getVersionType().nullSafeGet( rs, getVersionColumnName(), session, null ); 1073 } 1074 finally { 1075 rs.close(); 1076 } 1077 } 1078 finally { 1079 session.getBatcher().closeStatement( st ); 1080 } 1081 1082 } 1083 catch ( SQLException sqle ) { 1084 throw JDBCExceptionHelper.convert( 1085 getFactory().getSQLExceptionConverter(), 1086 sqle, 1087 "could not retrieve version: " + 1088 MessageHelper.infoString( this, id, getFactory() ), 1089 getVersionSelectString() 1090 ); 1091 } 1092 1093 } 1094 1095 1098 protected String generateLockString(LockMode lockMode) { 1099 1100 SimpleSelect select = new SimpleSelect( getFactory().getDialect() ) 1101 .setLockMode( lockMode ) 1102 .setTableName( getVersionedTableName() ) 1103 .addColumn( rootTableKeyColumnNames[0] ) 1104 .addCondition( rootTableKeyColumnNames, "=?" ); 1105 if ( isVersioned() ) { 1106 select.addWhereToken( "and" ) 1107 .addCondition( getVersionColumnName(), "=?" ); 1108 } 1109 if ( getFactory().getSettings().isCommentsEnabled() ) { 1110 select.setComment( "lock " + getEntityName() ); 1111 } 1112 return select.toStatementString(); 1113 1114 } 1115 1116 protected void initLockers() { 1117 lockers.put( LockMode.READ, generateLockString( LockMode.READ ) ); 1118 lockers.put( LockMode.UPGRADE, generateLockString( LockMode.UPGRADE ) ); 1119 lockers.put( LockMode.UPGRADE_NOWAIT, generateLockString( LockMode.UPGRADE_NOWAIT ) ); 1120 } 1121 1122 public String [] toColumns(String alias, String propertyName) throws QueryException { 1123 return propertyMapping.toColumns( alias, propertyName ); 1124 } 1125 1126 public String [] toColumns(String propertyName) throws QueryException { 1127 return propertyMapping.getColumnNames( propertyName ); 1128 } 1129 1130 public Type toType(String propertyName) throws QueryException { 1131 return propertyMapping.toType( propertyName ); 1132 } 1133 1134 public String [] getPropertyColumnNames(String propertyName) { 1135 return propertyMapping.getColumnNames( propertyName ); 1136 } 1137 1138 1146 public int getSubclassPropertyTableNumber(String propertyName) { 1147 final String rootPropertyName = StringHelper.root(propertyName); 1148 Type type = propertyMapping.toType(rootPropertyName); 1149 if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) { 1150 return 0; 1151 } 1152 if ( type.isComponentType() && !propertyName.equals(rootPropertyName) ) { 1153 String unrooted = StringHelper.unroot(propertyName); 1154 int idx = ArrayHelper.indexOf( getSubclassColumnClosure(), unrooted ); 1155 if ( idx != -1 ) { 1156 return getSubclassColumnTableNumberClosure()[idx]; 1157 } 1158 } 1159 int index = ArrayHelper.indexOf( getSubclassPropertyNameClosure(), rootPropertyName); return index==-1 ? 0 : getSubclassPropertyTableNumber(index); 1161 } 1162 1163 protected String generateTableAlias(String rootAlias, int tableNumber) { 1164 if ( tableNumber == 0 ) return rootAlias; 1165 StringBuffer buf = new StringBuffer ().append( rootAlias ); 1166 if ( !rootAlias.endsWith( "_" ) ) buf.append( '_' ); 1167 return buf.append( tableNumber ).append( '_' ).toString(); 1168 } 1169 1170 public String [] toColumns(String name, final int i) { 1171 final String alias = generateTableAlias( name, getSubclassPropertyTableNumber( i ) ); 1172 String [] cols = getSubclassPropertyColumnNames( i ); 1173 String [] templates = getSubclassPropertyFormulaTemplateClosure()[i]; 1174 String [] result = new String [cols.length]; 1175 for ( int j = 0; j < cols.length; j++ ) { 1176 if ( cols[j] == null ) { 1177 result[j] = StringHelper.replace( templates[j], Template.TEMPLATE, alias ); 1178 } 1179 else { 1180 result[j] = StringHelper.qualify( alias, cols[j] ); 1181 } 1182 } 1183 return result; 1184 } 1185 1186 private int getSubclassPropertyIndex(String propertyName) { 1187 return ArrayHelper.indexOf(subclassPropertyNameClosure, propertyName); 1188 } 1189 1190 protected String [] getPropertySubclassNames() { 1191 return propertySubclassNames; 1192 } 1193 1194 public String [] getPropertyColumnNames(int i) { 1195 return propertyColumnNames[i]; 1196 } 1197 1198 protected int getPropertyColumnSpan(int i) { 1199 return propertyColumnSpans[i]; 1200 } 1201 1202 protected boolean hasFormulaProperties() { 1203 return hasFormulaProperties; 1204 } 1205 1206 public FetchMode getFetchMode(int i) { 1207 return subclassPropertyFetchModeClosure[i]; 1208 } 1209 1210 public Type getSubclassPropertyType(int i) { 1211 return subclassPropertyTypeClosure[i]; 1212 } 1213 1214 public String getSubclassPropertyName(int i) { 1215 return subclassPropertyNameClosure[i]; 1216 } 1217 1218 public int countSubclassProperties() { 1219 return subclassPropertyTypeClosure.length; 1220 } 1221 1222 public String [] getSubclassPropertyColumnNames(int i) { 1223 return subclassPropertyColumnNameClosure[i]; 1224 } 1225 1226 public boolean isDefinedOnSubclass(int i) { 1227 return propertyDefinedOnSubclass[i]; 1228 } 1229 1230 protected String [][] getSubclassPropertyFormulaTemplateClosure() { 1231 return subclassPropertyFormulaTemplateClosure; 1232 } 1233 1234 protected Type[] getSubclassPropertyTypeClosure() { 1235 return subclassPropertyTypeClosure; 1236 } 1237 1238 protected String [][] getSubclassPropertyColumnNameClosure() { 1239 return subclassPropertyColumnNameClosure; 1240 } 1241 1242 protected String [] getSubclassPropertyNameClosure() { 1243 return subclassPropertyNameClosure; 1244 } 1245 1246 protected String [] getSubclassPropertySubclassNameClosure() { 1247 return subclassPropertySubclassNameClosure; 1248 } 1249 1250 protected String [] getSubclassColumnClosure() { 1251 return subclassColumnClosure; 1252 } 1253 1254 protected String [] getSubclassColumnAliasClosure() { 1255 return subclassColumnAliasClosure; 1256 } 1257 1258 protected String [] getSubclassFormulaClosure() { 1259 return subclassFormulaClosure; 1260 } 1261 1262 protected String [] getSubclassFormulaTemplateClosure() { 1263 return subclassFormulaTemplateClosure; 1264 } 1265 1266 protected String [] getSubclassFormulaAliasClosure() { 1267 return subclassFormulaAliasClosure; 1268 } 1269 1270 public String [] getSubclassPropertyColumnAliases(String propertyName, String suffix) { 1271 String rawAliases[] = ( String [] ) subclassPropertyAliases.get( propertyName ); 1272 1273 if ( rawAliases == null ) return null; 1274 1275 String result[] = new String [rawAliases.length]; 1276 for ( int i = 0; i < rawAliases.length; i++ ) { 1277 result[i] = new Alias( suffix ).toUnquotedAliasString( rawAliases[i] ); 1278 } 1279 return result; 1280 } 1281 1282 public String [] getSubclassPropertyColumnNames(String propertyName) { 1283 return ( String [] ) subclassPropertyColumnNames.get( propertyName ); 1285 } 1286 1287 1288 1289 1293 protected void initSubclassPropertyAliasesMap(PersistentClass model) throws MappingException { 1294 1295 internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosureIterator() ); 1297 1298 subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() ); 1300 subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() ); 1301 1302 if ( hasIdentifierProperty() ) { 1304 subclassPropertyAliases.put( getIdentifierPropertyName(), getIdentifierAliases() ); 1305 subclassPropertyColumnNames.put( getIdentifierPropertyName(), getIdentifierColumnNames() ); 1306 } 1307 1308 if ( getIdentifierType().isComponentType() ) { 1310 AbstractComponentType componentId = ( AbstractComponentType ) getIdentifierType(); 1312 String [] idPropertyNames = componentId.getPropertyNames(); 1313 String [] idAliases = getIdentifierAliases(); 1314 String [] idColumnNames = getIdentifierColumnNames(); 1315 1316 for ( int i = 0; i < idPropertyNames.length; i++ ) { 1317 subclassPropertyAliases.put( 1318 ENTITY_ID + "." + idPropertyNames[i], 1319 new String [] { idAliases[i] } 1320 ); 1321 subclassPropertyColumnNames.put( 1322 ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyNames[i], 1323 new String [] { idColumnNames[i] } 1324 ); 1325 if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyName() ) ) { 1326 subclassPropertyAliases.put( 1327 getIdentifierPropertyName() + "." + idPropertyNames[i], 1328 new String [] { idAliases[i] } 1329 ); 1330 subclassPropertyColumnNames.put( 1331 getIdentifierPropertyName() + "." + idPropertyNames[i], 1332 new String [] { idColumnNames[i] } 1333 ); 1334 } 1335 else { 1336 subclassPropertyAliases.put( idPropertyNames[i], new String [] { idAliases[i] } ); 1338 subclassPropertyColumnNames.put( idPropertyNames[i], new String [] { idColumnNames[i] } ); 1339 } 1340 } 1341 } 1342 1343 if ( entityMetamodel.isPolymorphic() ) { 1344 subclassPropertyAliases.put( ENTITY_CLASS, 1345 new String []{getDiscriminatorAlias()} ); 1346 subclassPropertyColumnNames.put( ENTITY_CLASS, 1347 new String []{getDiscriminatorColumnName()} ); 1348 } 1349 1350 } 1351 1352 private void internalInitSubclassPropertyAliasesMap(String path, Iterator propertyIterator) { 1353 while ( propertyIterator.hasNext() ) { 1354 1355 Property prop = ( Property ) propertyIterator.next(); 1356 String propname = path == null ? prop.getName() : path + "." + prop.getName(); 1357 if ( prop.isComposite() ) { 1358 Component component = ( Component ) prop.getValue(); 1359 Iterator compProps = component.getPropertyIterator(); 1360 internalInitSubclassPropertyAliasesMap( propname, compProps ); 1361 } 1362 else { 1363 String [] aliases = new String [prop.getColumnSpan()]; 1364 String [] cols = new String [prop.getColumnSpan()]; 1365 Iterator colIter = prop.getColumnIterator(); 1366 int l = 0; 1367 while ( colIter.hasNext() ) { 1368 Selectable thing = ( Selectable ) colIter.next(); 1369 aliases[l] = thing.getAlias( getFactory().getDialect(), prop.getValue().getTable() ); 1370 cols[l] = thing.getText( getFactory().getDialect() ); l++; 1372 } 1373 1374 subclassPropertyAliases.put( propname, aliases ); 1375 subclassPropertyColumnNames.put( propname, cols ); 1376 } 1377 } 1378 1379 } 1380 1381 public Object loadByUniqueKey(String propertyName, Object uniqueKey, SessionImplementor session) 1382 throws HibernateException { 1383 return getAppropriateUniqueKeyLoader( propertyName, session.getEnabledFilters() ) 1384 .loadByUniqueKey( session, uniqueKey ); 1385 } 1386 1387 private EntityLoader getAppropriateUniqueKeyLoader(String propertyName, Map enabledFilters) { 1388 1389 final boolean useStaticLoader = ( enabledFilters == null || enabledFilters.isEmpty() ) 1390 && propertyName.indexOf('.')<0; 1392 if ( useStaticLoader ) { 1393 return (EntityLoader) uniqueKeyLoaders.get( propertyName ); 1394 } 1395 else { 1396 return createUniqueKeyLoader( 1397 propertyMapping.toType(propertyName), 1398 propertyMapping.toColumns(propertyName), 1399 enabledFilters 1400 ); 1401 } 1402 } 1403 1404 public int getPropertyIndex(String propertyName) { 1405 return entityMetamodel.getPropertyIndex(propertyName); 1406 } 1407 1408 protected void createUniqueKeyLoaders() throws MappingException { 1409 Type[] propertyTypes = getPropertyTypes(); 1410 String [] propertyNames = getPropertyNames(); 1411 for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 1412 if ( propertyUniqueness[i] ) { 1413 uniqueKeyLoaders.put( 1415 propertyNames[i], 1416 createUniqueKeyLoader( 1417 propertyTypes[i], 1418 getPropertyColumnNames( i ), 1419 CollectionHelper.EMPTY_MAP 1420 ) 1421 ); 1422 } 1424 } 1425 } 1426 1427 private EntityLoader createUniqueKeyLoader(Type uniqueKeyType, String [] columns, Map enabledFilters) { 1428 if ( uniqueKeyType.isEntityType() ) { 1429 String className = ( ( EntityType ) uniqueKeyType ).getAssociatedEntityName(); 1430 uniqueKeyType = getFactory().getEntityPersister( className ).getIdentifierType(); 1431 } 1432 1433 return new EntityLoader( this, columns, uniqueKeyType, 1, LockMode.NONE, getFactory(), enabledFilters ); 1434 } 1435 1436 protected String getSQLWhereString(String alias) { 1437 return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias ); 1438 } 1439 1440 protected boolean hasWhere() { 1441 return sqlWhereString != null; 1442 } 1443 1444 private void initOrdinaryPropertyPaths(Mapping mapping) throws MappingException { 1445 for ( int i = 0; i < getSubclassPropertyNameClosure().length; i++ ) { 1446 propertyMapping.initPropertyPaths( getSubclassPropertyNameClosure()[i], 1447 getSubclassPropertyTypeClosure()[i], 1448 getSubclassPropertyColumnNameClosure()[i], 1449 getSubclassPropertyFormulaTemplateClosure()[i], 1450 mapping ); 1451 } 1452 } 1453 1454 private void initIdentifierPropertyPaths(Mapping mapping) throws MappingException { 1455 String idProp = getIdentifierPropertyName(); 1456 if ( idProp != null ) { 1457 propertyMapping.initPropertyPaths( idProp, getIdentifierType(), getIdentifierColumnNames(), null, mapping ); 1458 } 1459 if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { 1460 propertyMapping.initPropertyPaths( null, getIdentifierType(), getIdentifierColumnNames(), null, mapping ); 1461 } 1462 propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getIdentifierColumnNames(), null, mapping ); 1463 } 1464 1465 private void initDiscriminatorPropertyPath(Mapping mapping) throws MappingException { 1466 propertyMapping.initPropertyPaths( ENTITY_CLASS, 1467 getDiscriminatorType(), 1468 new String []{getDiscriminatorColumnName()}, 1469 new String []{getDiscriminatorFormulaTemplate()}, 1470 getFactory() ); 1471 } 1472 1473 protected void initPropertyPaths(Mapping mapping) throws MappingException { 1474 initOrdinaryPropertyPaths(mapping); 1475 initOrdinaryPropertyPaths(mapping); initIdentifierPropertyPaths(mapping); 1477 if ( entityMetamodel.isPolymorphic() ) initDiscriminatorPropertyPath(mapping); 1478 } 1479 1480 protected UniqueEntityLoader createEntityLoader(LockMode lockMode, Map enabledFilters) throws MappingException { 1481 return BatchingEntityLoader.createBatchingEntityLoader( this, batchSize, lockMode, getFactory(), enabledFilters ); 1483 } 1484 1485 protected UniqueEntityLoader createEntityLoader(LockMode lockMode) throws MappingException { 1486 return createEntityLoader( lockMode, CollectionHelper.EMPTY_MAP ); 1487 } 1488 1489 protected boolean check(int rows, Serializable id, int tableNumber) throws HibernateException { 1490 if ( rows < 1 ) { 1491 if ( !isNullableTable( tableNumber ) ) { 1492 throw new StaleObjectStateException( getEntityName(), id ); 1493 } 1494 } 1495 else if ( rows > 1 ) { 1496 throw new HibernateException( 1497 "Duplicate identifier in table for: " + 1498 MessageHelper.infoString( this, id, getFactory() ) 1499 ); 1500 } 1501 return rows > 0; } 1503 1504 protected String generateUpdateString(boolean[] includeProperty, int j, boolean useRowId) { 1505 return generateUpdateString( includeProperty, j, null, useRowId ); 1506 } 1507 1508 1511 protected String generateUpdateString(final boolean[] includeProperty, 1512 final int j, 1513 final Object [] oldFields, 1514 final boolean useRowId) { 1515 1516 Update update = new Update().setTableName( getTableName( j ) ); 1517 1518 if ( useRowId ) { 1520 update.setPrimaryKeyColumnNames( new String []{rowIdName} ); } 1522 else { 1523 update.setPrimaryKeyColumnNames( getKeyColumns( j ) ); 1524 } 1525 1526 boolean hasColumns = false; 1527 for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 1528 if ( includeProperty[i] && isPropertyOfTable( i, j ) ) { 1529 update.addColumns( getPropertyColumnNames(i), propertyColumnUpdateable[i] ); 1531 hasColumns = hasColumns || getPropertyColumnSpan( i ) > 0; 1532 } 1533 } 1534 1535 if ( j == 0 && isVersioned() && entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_VERSION ) { 1536 if ( includeProperty[ getVersionProperty() ] ) { update.setVersionColumnName( getVersionColumnName() ); 1540 hasColumns = true; 1541 } 1542 } 1543 else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION && oldFields != null ) { 1544 1546 boolean[] includeInWhere = entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_ALL ? 1547 getPropertyUpdateability() : includeProperty; 1550 for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 1551 boolean[] versionability = getPropertyVersionability(); 1552 Type[] types = getPropertyTypes(); 1553 boolean include = includeInWhere[i] && 1554 isPropertyOfTable( i, j ) && 1555 versionability[i]; 1556 if ( include ) { 1557 String [] propertyColumnNames = getPropertyColumnNames( i ); 1560 boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() ); 1561 for ( int k=0; k<propertyNullness.length; k++ ) { 1562 if ( propertyNullness[k] ) { 1563 update.addWhereColumn( propertyColumnNames[k] ); 1564 } 1565 else { 1566 update.addWhereColumn( propertyColumnNames[k], " is null" ); 1567 } 1568 } 1569 } 1570 } 1571 1572 } 1573 1574 if ( getFactory().getSettings().isCommentsEnabled() ) { 1575 update.setComment( "update " + getEntityName() ); 1576 } 1577 1578 return hasColumns ? update.toStatementString() : null; 1579 } 1580 1581 protected String generateInsertString(boolean[] includeProperty, int j) { 1582 return generateInsertString( false, includeProperty, j ); 1583 } 1584 1585 protected String generateInsertString(boolean identityInsert, boolean[] includeProperty) { 1586 return generateInsertString( identityInsert, includeProperty, 0 ); 1587 } 1588 1589 1592 protected String generateInsertString(boolean identityInsert, boolean[] includeProperty, int j) { 1593 1594 Insert insert = new Insert( getFactory().getDialect() ) 1595 .setTableName( getTableName( j ) ); 1596 1597 for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 1599 if ( includeProperty[i] && isPropertyOfTable( i, j ) ) { 1600 insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i] ); 1602 } 1603 } 1604 1605 if ( j == 0 ) addDiscriminatorToInsert( insert ); 1607 1608 if ( j == 0 && identityInsert ) { 1610 insert.addIdentityColumn( getKeyColumns( 0 )[0] ); 1611 } 1612 else { 1613 insert.addColumns( getKeyColumns( j ) ); 1614 } 1615 1616 if ( getFactory().getSettings().isCommentsEnabled() ) { 1617 insert.setComment( "insert " + getEntityName() ); 1618 } 1619 1620 String result = insert.toStatementString(); 1621 1622 if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { result = getFactory().getDialect().appendIdentitySelectToInsert( result ); 1625 } 1626 1627 return result; 1628 } 1629 1630 1633 protected String generateDeleteString(int j) { 1634 Delete delete = new Delete() 1635 .setTableName( getTableName( j ) ) 1636 .setPrimaryKeyColumnNames( getKeyColumns( j ) ); 1637 if ( j == 0 ) delete.setVersionColumnName( getVersionColumnName() ); 1638 if ( getFactory().getSettings().isCommentsEnabled() ) { 1639 delete.setComment( "delete " + getEntityName() ); 1640 } 1641 return delete.toStatementString(); 1642 } 1643 1644 protected int dehydrate( 1645 Serializable id, 1646 Object [] fields, 1647 boolean[] includeProperty, 1648 boolean[][] includeColumns, 1649 int j, 1650 PreparedStatement st, 1651 SessionImplementor session) 1652 throws HibernateException, SQLException { 1653 return dehydrate( id, fields, null, includeProperty, includeColumns, j, st, session, 1 ); 1654 } 1655 1656 1659 protected int dehydrate(final Serializable id, 1660 final Object [] fields, 1661 final Object rowId, 1662 final boolean[] includeProperty, 1663 final boolean[][] includeColumns, 1664 final int j, 1665 final PreparedStatement ps, 1666 final SessionImplementor session, 1667 int index) 1668 throws SQLException , HibernateException { 1669 1670 if ( log.isTraceEnabled() ) { 1671 log.trace( "Dehydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 1672 } 1673 1674 for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 1675 if ( includeProperty[i] && isPropertyOfTable( i, j ) ) { 1676 getPropertyTypes()[i].nullSafeSet( ps, fields[i], index, includeColumns[i], session ); 1677 index += ArrayHelper.countTrue( includeColumns[i] ); } 1680 } 1681 1682 if ( rowId != null ) { 1683 ps.setObject( index, rowId ); 1684 index += 1; 1685 } 1686 else if ( id != null ) { 1687 getIdentifierType().nullSafeSet( ps, id, index, session ); 1688 index += getIdentifierColumnSpan(); 1689 } 1690 1691 return index; 1692 1693 } 1694 1695 1700 public Object [] hydrate(final ResultSet rs, 1701 final Serializable id, 1702 final Object object, 1703 final Loadable rootLoadable, 1704 final String [][] suffixedPropertyColumns, 1705 final boolean allProperties, 1706 final SessionImplementor session) 1707 throws SQLException , HibernateException { 1708 1709 if ( log.isTraceEnabled() ) { 1710 log.trace( "Hydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 1711 } 1712 1713 final BasicEntityPersister rootPersister = (BasicEntityPersister) rootLoadable; 1714 1715 final boolean hasDeferred = rootPersister.hasSequentialSelect(); 1716 PreparedStatement sequentialSelect = null; 1717 ResultSet sequentialResultSet = null; 1718 try { 1719 1720 if ( hasDeferred ) { 1721 final String sql = rootPersister.getSequentialSelect( getEntityName() ); 1722 if ( sql != null ) { 1723 sequentialSelect = session.getBatcher().prepareSelectStatement( sql ); 1725 rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session ); 1726 sequentialResultSet = sequentialSelect.executeQuery(); 1727 sequentialResultSet.next(); 1728 } 1729 } 1730 1731 final String [] propNames = getPropertyNames(); 1732 final Type[] types = getPropertyTypes(); 1733 final Object [] values = new Object [types.length]; 1734 final boolean[] laziness = getPropertyLaziness(); 1735 final String [] propSubclassNames = getSubclassPropertySubclassNameClosure(); 1736 1737 for ( int i = 0; i < types.length; i++ ) { 1738 if ( !propertySelectable[i] ) { 1739 values[i] = BackrefPropertyAccessor.UNKNOWN; 1740 } 1741 else if ( allProperties || !laziness[i] ) { 1742 final boolean propertyIsDeferred = hasDeferred && 1744 rootPersister.isSubclassPropertyDeferred( propNames[i], propSubclassNames[i] ); 1745 final ResultSet propertyResultSet = propertyIsDeferred ? sequentialResultSet : rs; 1746 final String [] cols = propertyIsDeferred ? 1747 propertyColumnAliases[i] : suffixedPropertyColumns[i]; 1748 1749 values[i] = types[i].hydrate( propertyResultSet, cols, session, object ); 1750 } 1751 else { 1752 values[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY; 1753 } 1754 } 1755 1756 if ( sequentialResultSet != null ) sequentialResultSet.close(); 1757 1758 return values; 1759 1760 } 1761 finally { 1762 if ( sequentialSelect != null ) { 1763 session.getBatcher().closeStatement( sequentialSelect ); 1764 } 1765 } 1766 } 1767 1768 protected boolean useInsertSelectIdentity() { 1769 return !useGetGeneratedKeys() && getFactory().getDialect().supportsInsertSelectIdentity(); 1770 } 1771 1772 protected boolean useGetGeneratedKeys() { 1773 return getFactory().getSettings().isGetGeneratedKeysEnabled(); 1774 } 1775 1776 protected String getSequentialSelect(String entityName) { 1777 throw new UnsupportedOperationException ("no sequential selects"); 1778 } 1779 1780 1783 protected Serializable insert(final Object [] fields, 1784 final boolean[] notNull, 1785 String sql, 1786 final Object object, 1787 final SessionImplementor session) 1788 throws HibernateException { 1789 1790 if ( log.isTraceEnabled() ) { 1791 log.trace( "Inserting entity: " + getEntityName() + " (native id)" ); 1792 if ( isVersioned() ) log.trace( "Version: " + Versioning.getVersion( fields, this ) ); 1793 } 1794 1795 try { 1796 1797 PreparedStatement insert = session.getBatcher().prepareStatement( sql, useGetGeneratedKeys() ); 1799 try { 1800 dehydrate( null, fields, notNull, propertyColumnInsertable, 0, insert, session ); 1801 1802 if ( useInsertSelectIdentity() ) { 1803 if ( !insert.execute() ) { 1804 while ( !insert.getMoreResults() && insert.getUpdateCount() != -1 ) { 1805 continue; } 1807 } 1808 ResultSet rs = insert.getResultSet(); 1810 try { 1811 return IdentifierGeneratorFactory.getGeneratedIdentity( rs, getIdentifierType() ); 1812 } 1813 finally { 1814 rs.close(); 1815 } 1816 } 1817 else if ( useGetGeneratedKeys() ) { 1818 insert.executeUpdate(); 1819 return IdentifierGeneratorFactory.getGeneratedIdentity( 1821 GetGeneratedKeysHelper.getGeneratedKey(insert), 1822 getIdentifierType() 1823 ); 1824 } 1825 else { 1826 insert.executeUpdate(); 1827 } 1828 1829 } 1830 finally { 1831 session.getBatcher().closeStatement( insert ); 1832 } 1833 1834 } 1835 catch ( SQLException sqle ) { 1836 throw JDBCExceptionHelper.convert( 1837 getFactory().getSQLExceptionConverter(), 1838 sqle, 1839 "could not insert: " + MessageHelper.infoString(this), 1840 sql 1841 ); 1842 } 1843 1844 return ( (PostInsertIdentifierGenerator) getIdentifierGenerator() ).getGenerated(session, object, this); 1845 1846 } 1847 1848 public String getIdentitySelectString() { 1849 return getFactory().getDialect().getIdentitySelectString( 1851 getTableName(0), 1852 getKeyColumns(0)[0], 1853 getIdentifierType().sqlTypes( getFactory() )[0] 1854 ); 1855 } 1856 1857 public String getSelectByUniqueKeyString(String propertyName) { 1858 return new SimpleSelect( getFactory().getDialect() ) 1859 .setTableName( getTableName(0) ) 1860 .addColumns( getKeyColumns(0) ) 1861 .addCondition( getPropertyColumnNames(propertyName), "=?" ) 1862 .toStatementString(); 1863 } 1864 1865 1868 protected void insert(final Serializable id, 1869 final Object [] fields, 1870 final boolean[] notNull, 1871 final int j, 1872 final String sql, 1873 final Object object, 1874 final SessionImplementor session) 1875 throws HibernateException { 1876 1877 if ( isInverseTable( j ) ) return; 1878 1879 if ( isNullableTable( j ) && isAllNull( fields, j ) ) return; 1882 1883 if ( log.isTraceEnabled() ) { 1884 log.trace( "Inserting entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 1885 if ( j == 0 && isVersioned() ) log.trace( "Version: " + Versioning.getVersion( fields, this ) ); 1886 } 1887 1888 boolean callable = isInsertCallable( j ); 1889 final boolean useBatch = j == 0 && !callable; try { 1891 1892 final PreparedStatement insert; 1894 if ( callable ) { 1895 insert = session.getBatcher().prepareCallableStatement( sql ); 1896 } 1897 else if ( useBatch ) { 1898 insert = session.getBatcher().prepareBatchStatement( sql ); 1899 } 1900 else { 1901 insert = session.getBatcher().prepareStatement( sql ); 1902 } 1903 1904 try { 1905 1906 1909 dehydrate( id, fields, notNull, propertyColumnInsertable, j, insert, session ); 1910 1911 if ( useBatch ) { 1912 session.getBatcher().addToBatch( 1 ); 1913 } 1914 else { 1915 insert.executeUpdate(); 1916 } 1917 1918 } 1919 catch ( SQLException sqle ) { 1920 if ( useBatch ) session.getBatcher().abortBatch( sqle ); 1921 throw sqle; 1922 } 1923 finally { 1924 if ( !useBatch ) session.getBatcher().closeStatement( insert ); 1925 } 1926 } 1927 catch ( SQLException sqle ) { 1928 throw JDBCExceptionHelper.convert( 1929 getFactory().getSQLExceptionConverter(), 1930 sqle, 1931 "could not insert: " + MessageHelper.infoString( this ), 1932 sql 1933 ); 1934 } 1935 1936 } 1937 1938 1941 protected void updateOrInsert(final Serializable id, 1942 final Object [] fields, 1943 final Object [] oldFields, 1944 final Object rowId, 1945 final boolean[] includeProperty, 1946 final int j, 1947 final Object oldVersion, 1948 final Object object, 1949 final String sql, 1950 final SessionImplementor session) 1951 throws HibernateException { 1952 1953 if ( !isInverseTable( j ) ) { 1954 1955 final boolean isRowToUpdate; 1956 if ( isNullableTable( j ) && oldFields != null && isAllNull( oldFields, j ) ) { 1957 isRowToUpdate = false; 1959 } 1960 else if ( isNullableTable( j ) && isAllNull( fields, j ) ) { 1961 isRowToUpdate = true; 1963 delete( id, oldVersion, j, object, getSQLDeleteStrings()[j], session ); 1964 } 1965 else { 1966 isRowToUpdate = update( id, fields, oldFields, rowId, includeProperty, j, oldVersion, object, sql, session ); 1969 } 1970 1971 if ( !isRowToUpdate && !isAllNull( fields, j ) ) { 1972 insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session ); 1976 } 1977 1978 } 1979 1980 } 1981 1982 protected boolean update(final Serializable id, 1983 final Object [] fields, 1984 final Object [] oldFields, 1985 final Object rowId, 1986 final boolean[] includeProperty, 1987 final int j, 1988 final Object oldVersion, 1989 final Object object, 1990 final String sql, 1991 final SessionImplementor session) 1992 throws HibernateException { 1993 1994 final boolean useVersion = j == 0 && isVersioned(); 1995 final boolean callable = isUpdateCallable( j ); 1996 final boolean useBatch = j == 0 && !callable && isBatchable(); 1998 if ( log.isTraceEnabled() ) { 1999 log.trace( "Updating entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 2000 if ( useVersion ) log.trace( "Existing version: " + oldVersion + " -> New version: " + fields[getVersionProperty()] ); 2001 } 2002 2003 try { 2004 2005 int index = 1; final PreparedStatement update; 2007 if ( callable ) { 2008 CallableStatement callstatement = session.getBatcher().prepareCallableStatement( sql ); 2009 callstatement.registerOutParameter( index++, Types.NUMERIC ); update = callstatement; 2011 } 2012 else if ( useBatch ) { 2013 update = session.getBatcher().prepareBatchStatement( sql ); 2014 } 2015 else { 2016 update = session.getBatcher().prepareStatement( sql ); 2017 } 2018 2019 try { 2020 2021 index = dehydrate( id, fields, rowId, includeProperty, propertyColumnUpdateable, j, update, session, index ); 2023 2024 if ( useVersion && Versioning.OPTIMISTIC_LOCK_VERSION == entityMetamodel.getOptimisticLockMode() ) { 2026 getVersionType().nullSafeSet( update, oldVersion, index, session ); 2027 } 2028 else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION && oldFields != null ) { 2029 boolean[] versionability = getPropertyVersionability(); boolean[] includeOldField = entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_ALL ? 2031 getPropertyUpdateability() : includeProperty; 2032 Type[] types = getPropertyTypes(); 2033 for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 2034 boolean include = includeOldField[i] && 2035 isPropertyOfTable( i, j ) && 2036 versionability[i]; if ( include ) { 2038 boolean[] settable = types[i].toColumnNullness( oldFields[i], getFactory() ); 2039 types[i].nullSafeSet( 2040 update, 2041 oldFields[i], 2042 index, 2043 settable, 2044 session 2045 ); 2046 index += ArrayHelper.countTrue(settable); 2047 } 2048 } 2049 } 2050 2051 if ( useBatch ) { 2052 session.getBatcher().addToBatch( 1 ); 2053 return true; 2054 } 2055 else { 2056 return check( update.executeUpdate(), id, j ); 2057 } 2058 2059 } 2060 catch ( SQLException sqle ) { 2061 if ( useBatch ) session.getBatcher().abortBatch( sqle ); 2062 throw sqle; 2063 } 2064 finally { 2065 if ( !useBatch ) session.getBatcher().closeStatement( update ); 2066 } 2067 2068 } 2069 catch ( SQLException sqle ) { 2070 throw JDBCExceptionHelper.convert( 2071 getFactory().getSQLExceptionConverter(), 2072 sqle, 2073 "could not update: " + MessageHelper.infoString( this, id, getFactory() ), 2074 sql 2075 ); 2076 } 2077 } 2078 2079 2082 protected void delete(final Serializable id, 2083 final Object version, 2084 final int j, 2085 final Object object, 2086 final String sql, 2087 final SessionImplementor session) 2088 throws HibernateException { 2089 2090 if ( isInverseTable( j ) ) return; 2091 2092 final boolean useVersion = j == 0 && isVersioned(); 2093 final boolean callable = isDeleteCallable( j ); 2094 final boolean useBatch = j == 0 && isBatchable() && !callable; 2095 2096 if ( log.isTraceEnabled() ) { 2097 log.trace( "Deleting entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 2098 if ( useVersion ) log.trace( "Version: " + version ); 2099 } 2100 2101 if ( isTableCascadeDeleteEnabled( j ) ) { 2102 if ( log.isTraceEnabled() ) { 2103 log.trace( "delete handled by foreign key constraint: " + getTableName( j ) ); 2104 } 2105 return; } 2107 2108 try { 2109 2110 PreparedStatement delete; 2112 int index = 1; 2113 if ( callable ) { 2114 CallableStatement callstatement = session.getBatcher().prepareCallableStatement( sql ); 2115 callstatement.registerOutParameter( index++, Types.NUMERIC ); delete = callstatement; 2117 } 2118 else if ( useBatch ) { 2119 delete = session.getBatcher().prepareBatchStatement( sql ); 2120 } 2121 else { 2122 delete = session.getBatcher().prepareStatement( sql ); 2123 } 2124 2125 try { 2126 2127 2130 getIdentifierType().nullSafeSet( delete, id, index, session ); 2131 2132 2134 if ( useVersion ) { 2135 getVersionType().nullSafeSet( delete, version, getIdentifierColumnSpan() + index, session ); 2136 } 2137 2138 if ( useBatch ) { 2139 session.getBatcher().addToBatch( 1 ); 2140 } 2141 else { 2142 check( delete.executeUpdate(), id, j ); 2143 } 2144 2145 } 2146 catch ( SQLException sqle ) { 2147 if ( useBatch ) session.getBatcher().abortBatch( sqle ); 2148 throw sqle; 2149 } 2150 finally { 2151 if ( !useBatch ) session.getBatcher().closeStatement( delete ); 2152 } 2153 2154 } 2155 catch ( SQLException sqle ) { 2156 throw JDBCExceptionHelper.convert( 2157 getFactory().getSQLExceptionConverter(), 2158 sqle, 2159 "could not delete: " + 2160 MessageHelper.infoString( this, id, getFactory() ), 2161 sql 2162 ); 2163 2164 } 2165 2166 } 2167 2168 private String [] getUpdateStrings(boolean byRowId, boolean lazy) { 2169 if ( byRowId ) { 2170 return lazy ? getSQLLazyUpdateByRowIdStrings() : getSQLUpdateByRowIdStrings(); 2171 } 2172 else { 2173 return lazy ? getSQLLazyUpdateStrings() : getSQLUpdateStrings(); 2174 } 2175 } 2176 2177 2180 public void update(final Serializable id, 2181 final Object [] fields, 2182 final int[] dirtyFields, 2183 final boolean hasDirtyCollection, 2184 final Object [] oldFields, 2185 final Object oldVersion, 2186 final Object object, 2187 final Object rowId, 2188 final SessionImplementor session) 2189 throws HibernateException { 2190 2191 2194 final boolean[] tableUpdateNeeded = getTableUpdateNeeded( dirtyFields, hasDirtyCollection ); 2195 final int span = getTableSpan(); 2196 2197 final boolean[] propsToUpdate; 2198 final String [] updateStrings; 2199 if ( entityMetamodel.isDynamicUpdate() && dirtyFields != null ) { 2200 propsToUpdate = getPropertiesToUpdate( dirtyFields, hasDirtyCollection ); 2202 updateStrings = new String [span]; 2204 for ( int j = 0; j < span; j++ ) { 2205 updateStrings[j] = tableUpdateNeeded[j] ? 2206 generateUpdateString( propsToUpdate, j, oldFields, j == 0 && rowId != null ) : 2207 null; 2208 } 2209 } 2210 else { 2211 updateStrings = getUpdateStrings( 2213 rowId != null, 2214 hasUninitializedLazyProperties( object, session.getEntityMode() ) 2215 ); 2216 propsToUpdate = getPropertyUpdateability( object, session.getEntityMode() ); 2217 } 2218 2219 for ( int j = 0; j < span; j++ ) { 2220 if ( tableUpdateNeeded[j] ) { 2222 updateOrInsert( 2223 id, 2224 fields, 2225 oldFields, 2226 j == 0 ? rowId : null, 2227 propsToUpdate, 2228 j, 2229 oldVersion, 2230 object, 2231 updateStrings[j], 2232 session 2233 ); 2234 } 2235 } 2236 } 2237 2238 public Serializable insert(Object [] fields, Object object, SessionImplementor session) 2239 throws HibernateException { 2240 2241 final int span = getTableSpan(); 2242 final Serializable id; 2243 if ( entityMetamodel.isDynamicInsert() ) { 2244 boolean[] notNull = getPropertiesToInsert( fields ); 2246 id = insert( fields, notNull, generateInsertString( true, notNull ), object, session ); 2247 for ( int j = 1; j < span; j++ ) { 2248 insert( id, fields, notNull, j, generateInsertString( notNull, j ), object, session ); 2249 } 2250 } 2251 else { 2252 id = insert( fields, getPropertyInsertability(), getSQLIdentityInsertString(), object, session ); 2254 for ( int j = 1; j < span; j++ ) { 2255 insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session ); 2256 } 2257 } 2258 return id; 2259 } 2260 2261 public void insert(Serializable id, Object [] fields, Object object, SessionImplementor session) 2262 throws HibernateException { 2263 2264 final int span = getTableSpan(); 2265 if ( entityMetamodel.isDynamicInsert() ) { 2266 boolean[] notNull = getPropertiesToInsert( fields ); 2268 for ( int j = 0; j < span; j++ ) { 2269 insert( id, fields, notNull, j, generateInsertString( notNull, j ), object, session ); 2270 } 2271 } 2272 else { 2273 for ( int j = 0; j < span; j++ ) { 2275 insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session ); 2276 } 2277 } 2278 } 2279 2280 2283 public void delete(Serializable id, Object version, Object object, SessionImplementor session) 2284 throws HibernateException { 2285 2286 final int span = getTableSpan(); 2287 for ( int j = span - 1; j >= 0; j-- ) { 2288 delete( id, version, j, object, getSQLDeleteStrings()[j], session ); 2289 } 2290 2291 } 2292 2293 protected void logStaticSQL() { 2294 if ( log.isDebugEnabled() ) { 2295 log.debug( "Static SQL for entity: " + getEntityName() ); 2296 if ( sqlLazySelectString != null ) log.debug( " Lazy select: " + sqlLazySelectString ); 2297 if ( sqlVersionSelectString != null ) log.debug( " Version select: " + sqlVersionSelectString ); 2298 if ( sqlSnapshotSelectString != null ) log.debug( " Snapshot select: " + sqlSnapshotSelectString ); 2299 for ( int j = 0; j < getTableSpan(); j++ ) { 2300 log.debug( " Insert " + j + ": " + getSQLInsertStrings()[j] ); 2301 log.debug( " Update " + j + ": " + getSQLUpdateStrings()[j] ); 2302 log.debug( " Delete " + j + ": " + getSQLDeleteStrings()[j] ); 2303 2304 } 2305 if ( sqlIdentityInsertString != null ) log.debug( " Identity insert: " + sqlIdentityInsertString ); 2306 if ( sqlUpdateByRowIdString != null ) log.debug( " Update by row id (all fields): " + sqlUpdateByRowIdString ); 2307 if ( sqlLazyUpdateByRowIdString != null ) log.debug( " Update by row id (non-lazy fields): " + sqlLazyUpdateByRowIdString ); 2308 } 2309 } 2310 2311 public String filterFragment(String alias, Map enabledFilters) throws MappingException { 2312 final StringBuffer sessionFilterFragment = new StringBuffer (); 2313 filterHelper.render( sessionFilterFragment, generateFilterConditionAlias( alias ), enabledFilters ); 2314 2315 return sessionFilterFragment.append( filterFragment( alias ) ).toString(); 2316 } 2317 2318 protected String generateFilterConditionAlias(String rootAlias) { 2319 return rootAlias; 2320 } 2321 2322 public String oneToManyFilterFragment(String alias) throws MappingException { 2323 return ""; 2324 } 2325 2326 public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) { 2327 return getSubclassTableSpan() == 1 ? 2328 "" : createJoin( alias, innerJoin, includeSubclasses ).toFromFragmentString(); 2330 } 2331 2332 public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) { 2333 return getSubclassTableSpan() == 1 ? 2334 "" : createJoin( alias, innerJoin, includeSubclasses ).toWhereFragmentString(); 2336 } 2337 2338 protected boolean isSubclassTableLazy(int j) { 2339 return false; 2340 } 2341 2342 protected JoinFragment createJoin(String name, boolean innerJoin, boolean includeSubclasses) { 2343 final String [] idCols = StringHelper.qualify( name, getIdentifierColumnNames() ); final JoinFragment join = getFactory().getDialect().createOuterJoinFragment(); 2345 final int tableSpan = getSubclassTableSpan(); 2346 for ( int j = 1; j < tableSpan; j++ ) { final boolean joinIsIncluded = isClassOrSuperclassTable( j ) || 2348 ( includeSubclasses && !isSubclassTableSequentialSelect( j ) && !isSubclassTableLazy( j ) ); 2349 if ( joinIsIncluded ) { 2350 join.addJoin( getSubclassTableName( j ), 2351 generateTableAlias( name, j ), 2352 idCols, 2353 getSubclassTableKeyColumns( j ), 2354 innerJoin && isClassOrSuperclassTable( j ) && !isInverseTable( j ) && !isNullableTable( j ) ? 2355 JoinFragment.INNER_JOIN : JoinFragment.LEFT_OUTER_JOIN ); 2358 } 2359 } 2360 return join; 2361 } 2362 2363 protected JoinFragment createJoin(int[] tableNumbers, String drivingAlias) { 2364 final String [] keyCols = StringHelper.qualify( drivingAlias, getSubclassTableKeyColumns( tableNumbers[0] ) ); 2365 final JoinFragment jf = getFactory().getDialect().createOuterJoinFragment(); 2366 for ( int i = 1; i < tableNumbers.length; i++ ) { final int j = tableNumbers[i]; 2368 jf.addJoin( getSubclassTableName( j ), 2369 generateTableAlias( getRootAlias(), j ), 2370 keyCols, 2371 getSubclassTableKeyColumns( j ), 2372 isInverseSubclassTable( j ) || isNullableSubclassTable( j ) ? 2373 JoinFragment.LEFT_OUTER_JOIN : 2374 JoinFragment.INNER_JOIN ); 2375 } 2376 return jf; 2377 } 2378 2379 protected SelectFragment createSelect(final int[] subclassColumnNumbers, 2380 final int[] subclassFormulaNumbers) { 2381 2382 SelectFragment selectFragment = new SelectFragment(); 2383 2384 int[] columnTableNumbers = getSubclassColumnTableNumberClosure(); 2385 String [] columnAliases = getSubclassColumnAliasClosure(); 2386 String [] columns = getSubclassColumnClosure(); 2387 for ( int i = 0; i < subclassColumnNumbers.length; i++ ) { 2388 if ( subclassColumnSelectableClosure[i] ) { 2389 int columnNumber = subclassColumnNumbers[i]; 2390 final String subalias = generateTableAlias( getRootAlias(), columnTableNumbers[columnNumber] ); 2391 selectFragment.addColumn( subalias, columns[columnNumber], columnAliases[columnNumber] ); 2392 } 2393 } 2394 2395 int[] formulaTableNumbers = getSubclassFormulaTableNumberClosure(); 2396 String [] formulaTemplates = getSubclassFormulaTemplateClosure(); 2397 String [] formulaAliases = getSubclassFormulaAliasClosure(); 2398 for ( int i = 0; i < subclassFormulaNumbers.length; i++ ) { 2399 int formulaNumber = subclassFormulaNumbers[i]; 2400 final String subalias = generateTableAlias( getRootAlias(), formulaTableNumbers[formulaNumber] ); 2401 selectFragment.addFormula( subalias, formulaTemplates[formulaNumber], formulaAliases[formulaNumber] ); 2402 } 2403 2404 return selectFragment; 2405 } 2406 2407 protected String createFrom(int tableNumber, String alias) { 2408 return getSubclassTableName( tableNumber ) + ' ' + alias; 2409 } 2410 2411 protected String createWhereByKey(int tableNumber, String alias) { 2412 return StringHelper.join( "=? and ", 2414 StringHelper.qualify( alias, getSubclassTableKeyColumns( tableNumber ) ) ) + "=?"; 2415 } 2416 2417 protected String renderSelect(final int[] tableNumbers, 2418 final int[] columnNumbers, 2419 final int[] formulaNumbers) { 2420 2421 Arrays.sort( tableNumbers ); 2423 int drivingTable = tableNumbers[0]; 2425 final String drivingAlias = generateTableAlias( getRootAlias(), drivingTable ); final String where = createWhereByKey( drivingTable, drivingAlias ); 2427 final String from = createFrom( drivingTable, drivingAlias ); 2428 2429 JoinFragment jf = createJoin( tableNumbers, drivingAlias ); 2431 2432 SelectFragment selectFragment = createSelect( columnNumbers, formulaNumbers ); 2434 2435 Select select = new Select( getFactory().getDialect() ); 2437 select.setSelectClause( selectFragment.toFragmentString().substring( 2 ) ); 2438 select.setFromClause( from ); 2439 select.setWhereClause( where ); 2440 select.setOuterJoins( jf.toFromFragmentString(), jf.toWhereFragmentString() ); 2441 if ( getFactory().getSettings().isCommentsEnabled() ) { 2442 select.setComment( "sequential select " + getEntityName() ); 2443 } 2444 return select.toStatementString(); 2445 } 2446 2447 private String getRootAlias() { 2448 return StringHelper.generateAlias( getEntityName() ); 2449 } 2450 2451 protected void postConstruct(Mapping mapping) throws MappingException { 2452 initPropertyPaths(mapping); 2453 2454 final int joinSpan = getTableSpan(); 2456 sqlDeleteStrings = new String [joinSpan]; 2457 sqlInsertStrings = new String [joinSpan]; 2458 sqlUpdateStrings = new String [joinSpan]; 2459 sqlLazyUpdateStrings = new String [joinSpan]; 2460 2461 sqlUpdateByRowIdString = rowIdName == null ? 2462 null : 2463 generateUpdateString( getPropertyUpdateability(), 0, true ); 2464 sqlLazyUpdateByRowIdString = rowIdName == null ? 2465 null : 2466 generateUpdateString( getNonLazyPropertyUpdateability(), 0, true ); 2467 2468 for ( int j = 0; j < joinSpan; j++ ) { 2469 sqlInsertStrings[j] = customSQLInsert[j] == null ? 2470 generateInsertString( getPropertyInsertability(), j ) : 2471 customSQLInsert[j]; 2472 sqlUpdateStrings[j] = customSQLUpdate[j] == null ? 2473 generateUpdateString( getPropertyUpdateability(), j, false ) : 2474 customSQLUpdate[j]; 2475 sqlLazyUpdateStrings[j] = customSQLUpdate[j] == null ? 2476 generateUpdateString( getNonLazyPropertyUpdateability(), j, false ) : 2477 customSQLUpdate[j]; 2478 sqlDeleteStrings[j] = customSQLDelete[j] == null ? 2479 generateDeleteString( j ) : 2480 customSQLDelete[j]; 2481 } 2482 2483 tableHasColumns = new boolean[joinSpan]; 2484 for ( int j = 0; j < joinSpan; j++ ) { 2485 tableHasColumns[j] = sqlUpdateStrings[j] != null; 2486 } 2487 2488 sqlSnapshotSelectString = generateSnapshotSelectString(); 2490 sqlLazySelectString = generateLazySelectString(); 2491 sqlVersionSelectString = generateSelectVersionString(); 2492 if ( isIdentifierAssignedByInsert() ) { 2493 sqlIdentityInsertString = customSQLInsert[0] == null ? 2494 generateInsertString( true, getPropertyInsertability() ) : 2495 customSQLInsert[0]; 2496 } 2497 else { 2498 sqlIdentityInsertString = null; 2499 } 2500 2501 logStaticSQL(); 2502 2503 } 2504 2505 public void postInstantiate() throws MappingException { 2506 2507 createLoaders(); 2508 createUniqueKeyLoaders(); 2509 createQueryLoader(); 2510 2511 } 2512 2513 private void createLoaders() { 2514 loaders.put( LockMode.NONE, createEntityLoader( LockMode.NONE ) ); 2515 2516 UniqueEntityLoader readLoader = createEntityLoader( LockMode.READ ); 2517 loaders.put( LockMode.READ, readLoader ); 2518 2519 boolean disableForUpdate = getSubclassTableSpan() > 1 && 2521 hasSubclasses() && 2522 !getFactory().getDialect().supportsOuterJoinForUpdate(); 2523 2524 loaders.put( LockMode.UPGRADE, 2525 disableForUpdate ? readLoader : createEntityLoader( LockMode.UPGRADE ) ); 2526 loaders.put( LockMode.UPGRADE_NOWAIT, 2527 disableForUpdate ? readLoader : createEntityLoader( LockMode.UPGRADE_NOWAIT ) ); 2528 } 2529 2530 protected void createQueryLoader() { 2531 if ( loaderName != null ) queryLoader = new NamedQueryLoader( loaderName, this ); 2532 } 2533 2534 2538 public Object load(Serializable id, Object optionalObject, LockMode lockMode, SessionImplementor session) 2539 throws HibernateException { 2540 2541 if ( log.isTraceEnabled() ) { 2542 log.trace( "Materializing entity: " + MessageHelper.infoString( this, id, getFactory() ) ); 2543 } 2544 2545 final UniqueEntityLoader loader = getAppropriateLoader( lockMode, session.getEnabledFilters() ); 2546 return loader.load( id, optionalObject, session ); 2547 } 2548 2549 private UniqueEntityLoader getAppropriateLoader(LockMode lockMode, Map enabledFilters) { 2550 if ( queryLoader != null ) { 2551 return queryLoader; 2552 } 2553 else if ( enabledFilters == null || enabledFilters.isEmpty() ) { 2554 return (UniqueEntityLoader) loaders.get( lockMode ); 2555 } 2556 else { 2557 return createEntityLoader( lockMode, enabledFilters ); 2558 } 2559 } 2560 2561 private boolean isAllNull(Object [] array, int tableNumber) { 2562 for ( int i = 0; i < array.length; i++ ) { 2563 if ( isPropertyOfTable( i, tableNumber ) && array[i] != null ) return false; 2564 } 2565 return true; 2566 } 2567 2568 public boolean isSubclassPropertyNullable(int i) { 2569 return subclassPropertyNullabilityClosure[i]; 2570 } 2571 2572 2576 protected final boolean[] getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection) { 2577 final boolean[] propsToUpdate = new boolean[ entityMetamodel.getPropertySpan() ]; 2578 final boolean[] updateability = getPropertyUpdateability(); for ( int j = 0; j < dirtyProperties.length; j++ ) { 2580 int property = dirtyProperties[j]; 2581 if ( updateability[property] ) propsToUpdate[property] = true; 2582 } 2583 if ( isVersioned() ) { 2584 propsToUpdate[ getVersionProperty() ] = 2585 Versioning.isVersionIncrementRequired( dirtyProperties, hasDirtyCollection, getPropertyVersionability() ); 2586 } 2587 return propsToUpdate; 2588 } 2589 2590 2594 protected boolean[] getPropertiesToInsert(Object [] fields) { 2595 boolean[] notNull = new boolean[fields.length]; 2596 boolean[] insertable = getPropertyInsertability(); 2597 for ( int i = 0; i < fields.length; i++ ) notNull[i] = insertable[i] && fields[i] != null; 2598 return notNull; 2599 } 2600 2601 2611 public int[] findDirty(Object [] currentState, Object [] previousState, Object entity, SessionImplementor session) 2612 throws HibernateException { 2613 int[] props = TypeFactory.findDirty( 2614 entityMetamodel.getProperties(), 2615 currentState, 2616 previousState, 2617 hasUninitializedLazyProperties( entity, session.getEntityMode() ), 2618 session 2619 ); 2620 if ( props == null ) { 2621 return null; 2622 } 2623 else { 2624 logDirtyProperties( props ); 2625 return props; 2626 } 2627 } 2628 2629 2639 public int[] findModified(Object [] old, Object [] current, Object entity, SessionImplementor session) 2640 throws HibernateException { 2641 int[] props = TypeFactory.findModified( 2642 entityMetamodel.getProperties(), 2643 current, 2644 old, 2645 hasUninitializedLazyProperties( entity, session.getEntityMode() ), 2646 session 2647 ); 2648 if ( props == null ) { 2649 return null; 2650 } 2651 else { 2652 logDirtyProperties( props ); 2653 return props; 2654 } 2655 } 2656 2657 2661 protected boolean[] getPropertyUpdateability(Object entity, EntityMode entityMode) { 2662 return hasUninitializedLazyProperties( entity, entityMode ) ? 2663 getNonLazyPropertyUpdateability() : 2664 getPropertyUpdateability(); 2665 } 2666 2667 private void logDirtyProperties(int[] props) { 2668 if ( log.isTraceEnabled() ) { 2669 for ( int i = 0; i < props.length; i++ ) { 2670 String propertyName = entityMetamodel.getProperties()[ props[i] ].getName(); 2671 log.trace( StringHelper.qualify( getEntityName(), propertyName ) + " is dirty" ); 2672 } 2673 } 2674 } 2675 2676 protected EntityTuplizer getTuplizer(SessionImplementor session) { 2677 return getTuplizer( session.getEntityMode() ); 2678 } 2679 2680 protected EntityTuplizer getTuplizer(EntityMode entityMode) { 2681 return entityMetamodel.getTuplizer( entityMode ); 2682 } 2683 2684 public SessionFactoryImplementor getFactory() { 2685 return factory; 2686 } 2687 2688 protected EntityMetamodel getEntityMetamodel() { 2689 return entityMetamodel; 2690 } 2691 2692 public boolean hasCache() { 2693 return cache != null; 2694 } 2695 2696 public CacheConcurrencyStrategy getCache() { 2697 return cache; 2698 } 2699 2700 public CacheEntryStructure getCacheEntryStructure() { 2701 return cacheEntryStructure; 2702 } 2703 2704 public final String getEntityName() { 2706 return entityMetamodel.getName(); 2707 } 2708 2709 public EntityType getEntityType() { 2710 return entityMetamodel.getEntityType(); 2711 } 2712 2713 private String getSubclassEntityName(Class clazz) { 2714 return ( String ) entityNameBySubclass.get( clazz ); 2715 } 2716 2717 public boolean isPolymorphic() { 2718 return entityMetamodel.isPolymorphic(); 2719 } 2720 2721 public boolean isInherited() { 2722 return entityMetamodel.isInherited(); 2723 } 2724 2725 public boolean hasCascades() { 2726 return entityMetamodel.hasCascades(); 2727 } 2728 2729 public boolean hasIdentifierProperty() { 2730 return !entityMetamodel.getIdentifierProperty().isVirtual(); 2731 } 2732 2733 public VersionType getVersionType() { 2734 return ( VersionType ) locateVersionType(); 2735 } 2736 2737 private Type locateVersionType() { 2738 return entityMetamodel.getVersionProperty() == null ? 2739 null : 2740 entityMetamodel.getVersionProperty().getType(); 2741 } 2742 2743 public int getVersionProperty() { 2744 return entityMetamodel.getVersionPropertyIndex(); 2745 } 2746 2747 public boolean isVersioned() { 2748 return entityMetamodel.isVersioned(); 2749 } 2750 2751 public boolean isIdentifierAssignedByInsert() { 2752 return entityMetamodel.getIdentifierProperty().isIdentifierAssignedByInsert(); 2753 } 2754 2755 protected boolean hasLazyProperties() { 2756 return entityMetamodel.hasLazyProperties(); 2757 } 2758 2759 2769 public void afterReassociate(Object entity, SessionImplementor session) { 2770 if ( entity instanceof InterceptFieldEnabled ) { 2772 FieldInterceptor interceptor = FieldInterceptor.getFieldInterceptor(entity); 2773 if ( interceptor != null ) { 2774 interceptor.setSession(session); 2775 } 2776 else { 2777 FieldInterceptor fieldInterceptor = FieldInterceptor.initFieldInterceptor( 2778 entity, 2779 getEntityName(), 2780 session, 2781 null 2782 ); 2783 fieldInterceptor.dirty(); 2784 } 2785 } 2786 } 2787 2788 public Boolean isTransient(Object entity, SessionImplementor session) throws HibernateException { 2789 final Serializable id; 2790 if ( hasIdentifierPropertyOrEmbeddedCompositeIdentifier() ) { 2791 id = getIdentifier( entity, session.getEntityMode() ); 2792 } 2793 else { 2794 id = null; 2795 } 2796 if ( id == null ) return Boolean.TRUE; 2799 2800 final Object version = getVersion( entity, session.getEntityMode() ); 2802 if ( isVersioned() ) { 2803 Boolean result = entityMetamodel.getVersionProperty() 2806 .getUnsavedValue().isUnsaved( version ); 2807 if ( result != null ) return result; 2808 } 2809 2810 Boolean result = entityMetamodel.getIdentifierProperty() 2812 .getUnsavedValue().isUnsaved( id ); 2813 if ( result != null ) return result; 2814 2815 if ( hasCache() ) { 2817 CacheKey ck = new CacheKey( 2818 id, 2819 getIdentifierType(), 2820 getRootEntityName(), 2821 session.getEntityMode(), 2822 session.getFactory() 2823 ); 2824 if ( getCache().get( ck, session.getTimestamp() ) != null ) { 2825 return Boolean.FALSE; 2826 } 2827 } 2828 2829 return null; 2830 } 2831 2832 public boolean hasCollections() { 2833 return entityMetamodel.hasCollections(); 2834 } 2835 2836 public boolean hasMutableProperties() { 2837 return entityMetamodel.hasMutableProperties(); 2838 } 2839 2840 public boolean isMutable() { 2841 return entityMetamodel.isMutable(); 2842 } 2843 2844 public boolean isAbstract() { 2845 return entityMetamodel.isAbstract(); 2846 } 2847 2848 public boolean hasSubclasses() { 2849 return entityMetamodel.hasSubclasses(); 2850 } 2851 2852 public boolean hasProxy() { 2853 return entityMetamodel.isLazy(); 2854 } 2855 2856 public IdentifierGenerator getIdentifierGenerator() throws HibernateException { 2857 return entityMetamodel.getIdentifierProperty().getIdentifierGenerator(); 2858 } 2859 2860 public String getRootEntityName() { 2861 return entityMetamodel.getRootName(); 2862 } 2863 2864 public ClassMetadata getClassMetadata() { 2865 return this; 2866 } 2867 2868 public String getMappedSuperclass() { 2869 return entityMetamodel.getSuperclass(); 2870 } 2871 2872 public boolean isExplicitPolymorphism() { 2873 return entityMetamodel.isExplicitPolymorphism(); 2874 } 2875 2876 protected boolean useDynamicUpdate() { 2877 return entityMetamodel.isDynamicUpdate(); 2878 } 2879 2880 protected boolean useDynamicInsert() { 2881 return entityMetamodel.isDynamicInsert(); 2882 } 2883 2884 protected boolean hasEmbeddedIdentifier() { 2885 return entityMetamodel.getIdentifierProperty().isEmbedded(); 2886 } 2887 2888 public boolean hasIdentifierPropertyOrEmbeddedCompositeIdentifier() { 2889 return hasIdentifierProperty() || hasEmbeddedIdentifier(); 2890 } 2891 2892 public String [] getKeyColumnNames() { 2893 return getIdentifierColumnNames(); 2894 } 2895 2896 public String getName() { 2897 return getEntityName(); 2898 } 2899 2900 public boolean isCollection() { 2901 return false; 2902 } 2903 2904 public boolean consumesEntityAlias() { 2905 return true; 2906 } 2907 2908 public boolean consumesCollectionAlias() { 2909 return false; 2910 } 2911 2912 public Type getPropertyType(String propertyName) throws MappingException { 2913 return propertyMapping.toType(propertyName); 2914 } 2915 2916 public Type getType() { 2917 return entityMetamodel.getEntityType(); 2918 } 2919 2920 public boolean isSelectBeforeUpdateRequired() { 2921 return entityMetamodel.isSelectBeforeUpdate(); 2922 } 2923 2924 protected final int optimisticLockMode() { 2925 return entityMetamodel.getOptimisticLockMode(); 2926 } 2927 2928 public Object createProxy(Serializable id, SessionImplementor session) throws HibernateException { 2929 return entityMetamodel.getTuplizer( session.getEntityMode() ) 2930 .createProxy( id, session ); 2931 } 2932 2933 public String toString() { 2934 return StringHelper.unqualify( getClass().getName() ) + 2935 '(' + entityMetamodel.getName() + ')'; 2936 } 2937 2938 public final String selectFragment( 2939 Joinable rhs, 2940 String rhsAlias, 2941 String lhsAlias, 2942 String entitySuffix, 2943 String collectionSuffix, 2944 boolean includeCollectionColumns) { 2945 return selectFragment( lhsAlias, entitySuffix ); 2946 } 2947 2948 protected boolean isInstrumented(EntityMode entityMode) { 2949 EntityTuplizer tuplizer = entityMetamodel.getTuplizerOrNull(entityMode); 2950 return tuplizer!=null && tuplizer.isInstrumented(); 2951 } 2952 2953 public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) { 2954 getTuplizer( session ).afterInitialize( entity, lazyPropertiesAreUnfetched, session ); 2955 } 2956 2957 public String [] getPropertyNames() { 2958 return entityMetamodel.getPropertyNames(); 2959 } 2960 2961 public Type[] getPropertyTypes() { 2962 return entityMetamodel.getPropertyTypes(); 2963 } 2964 2965 public boolean[] getPropertyLaziness() { 2966 return entityMetamodel.getPropertyLaziness(); 2967 } 2968 2969 public boolean[] getPropertyUpdateability() { 2970 return entityMetamodel.getPropertyUpdateability(); 2971 } 2972 2973 public boolean[] getPropertyCheckability() { 2974 return entityMetamodel.getPropertyCheckability(); 2975 } 2976 2977 public boolean[] getNonLazyPropertyUpdateability() { 2978 return entityMetamodel.getNonlazyPropertyUpdateability(); 2979 } 2980 2981 public boolean[] getPropertyInsertability() { 2982 return entityMetamodel.getPropertyInsertability(); 2983 } 2984 2985 public boolean[] getPropertyNullability() { 2986 return entityMetamodel.getPropertyNullability(); 2987 } 2988 2989 public boolean[] getPropertyVersionability() { 2990 return entityMetamodel.getPropertyVersionability(); 2991 } 2992 2993 public CascadeStyle[] getPropertyCascadeStyles() { 2994 return entityMetamodel.getCascadeStyles(); 2995 } 2996 2997 public final Class getMappedClass(EntityMode entityMode) { 2998 Tuplizer tup = entityMetamodel.getTuplizerOrNull(entityMode); 2999 return tup==null ? null : tup.getMappedClass(); 3000 } 3001 3002 public boolean implementsLifecycle(EntityMode entityMode) { 3003 return getTuplizer( entityMode ).isLifecycleImplementor(); 3004 } 3005 3006 public boolean implementsValidatable(EntityMode entityMode) { 3007 return getTuplizer( entityMode ).isValidatableImplementor(); 3008 } 3009 3010 public Class getConcreteProxyClass(EntityMode entityMode) { 3011 return getTuplizer( entityMode ).getConcreteProxyClass(); 3012 } 3013 3014 public void setPropertyValues(Object object, Object [] values, EntityMode entityMode) 3015 throws HibernateException { 3016 getTuplizer( entityMode ).setPropertyValues( object, values ); 3017 } 3018 3019 public void setPropertyValue(Object object, int i, Object value, EntityMode entityMode) 3020 throws HibernateException { 3021 getTuplizer( entityMode ).setPropertyValue( object, i, value ); 3022 } 3023 3024 public Object [] getPropertyValues(Object object, EntityMode entityMode) 3025 throws HibernateException { 3026 return getTuplizer( entityMode ).getPropertyValues( object ); 3027 } 3028 3029 public Object getPropertyValue(Object object, int i, EntityMode entityMode) 3030 throws HibernateException { 3031 return getTuplizer( entityMode ).getPropertyValue( object , i ); 3032 } 3033 3034 public Object getPropertyValue(Object object, String propertyName, EntityMode entityMode) 3035 throws HibernateException { 3036 return getTuplizer( entityMode ).getPropertyValue( object, propertyName ); 3037 } 3038 3039 public Serializable getIdentifier(Object object, EntityMode entityMode) 3040 throws HibernateException { 3041 return getTuplizer( entityMode ).getIdentifier( object ); 3042 } 3043 3044 public void setIdentifier(Object object, Serializable id, EntityMode entityMode) 3045 throws HibernateException { 3046 getTuplizer( entityMode ).setIdentifier( object, id ); 3047 } 3048 3049 public Object getVersion(Object object, EntityMode entityMode) 3050 throws HibernateException { 3051 return getTuplizer( entityMode ).getVersion( object ); 3052 } 3053 3054 public Object instantiate(Serializable id, EntityMode entityMode) 3055 throws HibernateException { 3056 return getTuplizer( entityMode ).instantiate( id ); 3057 } 3058 3059 public boolean isInstance(Object object, EntityMode entityMode) { 3060 return getTuplizer( entityMode ).isInstance( object ); 3061 } 3062 3063 public boolean hasUninitializedLazyProperties(Object object, EntityMode entityMode) { 3064 return getTuplizer( entityMode ).hasUninitializedLazyProperties( object ); 3065 } 3066 3067 public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion, EntityMode entityMode) { 3068 getTuplizer( entityMode ).resetIdentifier( entity, currentId, currentVersion ); 3069 } 3070 3071 public EntityPersister getSubclassEntityPersister(Object instance, SessionFactoryImplementor factory, EntityMode entityMode) { 3072 if ( !hasSubclasses() ) { 3073 return this; 3074 } 3075 else { 3076 Class clazz = instance.getClass(); 3077 if ( clazz == getMappedClass( entityMode ) ) { 3078 return this; 3079 } 3080 else { 3081 String subclassEntityName = getSubclassEntityName( clazz ); 3082 if ( subclassEntityName == null ) { 3083 throw new HibernateException( "instance not of expected entity type: " + getEntityName() ); 3084 } 3085 else { 3086 return factory.getEntityPersister( subclassEntityName ); 3087 } 3088 } 3089 } 3090 } 3091 3092 public EntityMode guessEntityMode(Object object) { 3093 return entityMetamodel.guessEntityMode(object); 3094 } 3095 3096 public boolean isMultiTable() { 3097 return false; 3098 } 3099 3100 public String getTemporaryIdTableName() { 3101 return temporaryIdTableName; 3102 } 3103 3104 public String getTemporaryIdTableDDL() { 3105 return temporaryIdTableDDL; 3106 } 3107 3108 protected int getPropertySpan() { 3109 return entityMetamodel.getPropertySpan(); 3110 } 3111 3112 public Object [] getPropertyValuesToInsert(Object object, Map mergeMap, SessionImplementor session) throws HibernateException { 3113 return getTuplizer( session.getEntityMode() ).getPropertyValuesToInsert( object, mergeMap, session ); 3114 } 3115 3116 public String getIdentifierPropertyName() { 3117 return entityMetamodel.getIdentifierProperty().getName(); 3118 } 3119 3120 public Type getIdentifierType() { 3121 return entityMetamodel.getIdentifierProperty().getType(); 3122 } 3123 3124 public boolean hasSubselectLoadableCollections() { 3125 return hasSubselectLoadableCollections; 3126 } 3127 3128 public int[] getNaturalIdentifierProperties() { 3129 return entityMetamodel.getNaturalIdentifierProperties(); 3130 } 3131 3132 public boolean hasNaturalIdentifier() { 3133 return entityMetamodel.hasNaturalIdentifier(); 3134 } 3135 3136 public void setPropertyValue(Object object, String propertyName, Object value, EntityMode entityMode) 3137 throws HibernateException { 3138 getTuplizer( entityMode ).setPropertyValue( object, propertyName, value ); 3139 } 3140 3142} 3143 | Popular Tags |