1 package org.hibernate.cfg; 3 4 import java.lang.reflect.AnnotatedElement ; 5 import java.lang.reflect.Field ; 6 import java.lang.reflect.Method ; 7 import java.util.ArrayList ; 8 import java.util.EnumSet ; 9 import java.util.HashMap ; 10 import java.util.HashSet ; 11 import java.util.Iterator ; 12 import java.util.List ; 13 import java.util.Map ; 14 import java.util.Properties ; 15 import java.util.ResourceBundle ; 16 import java.util.Set ; 17 import java.io.Serializable ; 18 import javax.persistence.AccessType; 19 import javax.persistence.Basic; 20 import javax.persistence.Column; 21 import javax.persistence.DiscriminatorType; 22 import javax.persistence.Embeddable; 23 import javax.persistence.Embedded; 24 import javax.persistence.EmbeddedId; 25 import javax.persistence.Entity; 26 import javax.persistence.FetchType; 27 import javax.persistence.GeneratedIdTable; 28 import javax.persistence.GeneratorType; 29 import javax.persistence.Id; 30 import javax.persistence.IdClass; 31 import javax.persistence.InheritanceType; 32 import javax.persistence.JoinColumn; 33 import javax.persistence.JoinColumns; 34 import javax.persistence.JoinTable; 35 import javax.persistence.Lob; 36 import javax.persistence.LobType; 37 import javax.persistence.ManyToMany; 38 import javax.persistence.ManyToOne; 39 import javax.persistence.MapKey; 40 import javax.persistence.NamedNativeQueries; 41 import javax.persistence.NamedNativeQuery; 42 import javax.persistence.NamedQueries; 43 import javax.persistence.NamedQuery; 44 import javax.persistence.OneToMany; 45 import javax.persistence.OneToOne; 46 import javax.persistence.PrimaryKeyJoinColumn; 47 import javax.persistence.PrimaryKeyJoinColumns; 48 import javax.persistence.SequenceGenerator; 49 import javax.persistence.SqlResultSetMapping; 50 import javax.persistence.TableGenerator; 51 import javax.persistence.Transient; 52 import javax.persistence.UniqueConstraint; 53 import javax.persistence.Version; 54 55 import org.apache.commons.logging.Log; 56 import org.apache.commons.logging.LogFactory; 57 import org.hibernate.AnnotationException; 58 import org.hibernate.AssertionFailure; 59 import org.hibernate.FetchMode; 60 import org.hibernate.MappingException; 61 import org.hibernate.annotations.BatchSize; 62 import org.hibernate.annotations.Cache; 63 import org.hibernate.annotations.Cascade; 64 import org.hibernate.annotations.CascadeType; 65 import org.hibernate.annotations.Check; 66 import org.hibernate.annotations.Columns; 67 import org.hibernate.annotations.Filter; 68 import org.hibernate.annotations.FilterDef; 69 import org.hibernate.annotations.FilterDefs; 70 import org.hibernate.annotations.Filters; 71 import org.hibernate.annotations.Formula; 72 import org.hibernate.annotations.OnDelete; 73 import org.hibernate.annotations.OnDeleteAction; 74 import org.hibernate.annotations.OrderBy; 75 import org.hibernate.annotations.ParamDef; 76 import org.hibernate.annotations.Parameter; 77 import org.hibernate.annotations.Proxy; 78 import org.hibernate.annotations.Sort; 79 import org.hibernate.annotations.Type; 80 import org.hibernate.annotations.TypeDef; 81 import org.hibernate.annotations.TypeDefs; 82 import org.hibernate.annotations.Where; 83 import org.hibernate.annotations.GenericGenerator; 84 import org.hibernate.annotations.Index; 85 import org.hibernate.cfg.annotations.CollectionBinder; 86 import org.hibernate.cfg.annotations.EntityBinder; 87 import org.hibernate.cfg.annotations.Nullability; 88 import org.hibernate.cfg.annotations.PropertyBinder; 89 import org.hibernate.cfg.annotations.QueryBinder; 90 import org.hibernate.cfg.annotations.SimpleValueBinder; 91 import org.hibernate.cfg.annotations.TableBinder; 92 import org.hibernate.engine.FilterDefinition; 93 import org.hibernate.engine.Versioning; 94 import org.hibernate.id.MultipleHiLoPerTableGenerator; 95 import org.hibernate.id.PersistentIdentifierGenerator; 96 import org.hibernate.id.TableHiLoGenerator; 97 import org.hibernate.mapping.Component; 98 import org.hibernate.mapping.DependantValue; 99 import org.hibernate.mapping.IdGenerator; 100 import org.hibernate.mapping.Join; 101 import org.hibernate.mapping.JoinedSubclass; 102 import org.hibernate.mapping.PersistentClass; 103 import org.hibernate.mapping.Property; 104 import org.hibernate.mapping.RootClass; 105 import org.hibernate.mapping.SimpleValue; 106 import org.hibernate.mapping.Subclass; 107 import org.hibernate.mapping.Table; 108 import org.hibernate.mapping.UnionSubclass; 109 import org.hibernate.persister.entity.JoinedSubclassEntityPersister; 110 import org.hibernate.persister.entity.SingleTableEntityPersister; 111 import org.hibernate.persister.entity.UnionSubclassEntityPersister; 112 import org.hibernate.type.ByteArrayBlobType; 113 import org.hibernate.type.CharacterArrayClobType; 114 import org.hibernate.type.EnumType; 115 import org.hibernate.type.ForeignKeyDirection; 116 import org.hibernate.type.PrimitiveByteArrayBlobType; 117 import org.hibernate.type.PrimitiveCharacterArrayClobType; 118 import org.hibernate.type.StringClobType; 119 import org.hibernate.type.TypeFactory; 120 import org.hibernate.type.SerializableToBlobType; 121 import org.hibernate.util.ReflectHelper; 122 import org.hibernate.util.StringHelper; 123 import org.hibernate.validator.ClassValidator; 124 125 134 public final class AnnotationBinder { 135 private static final String GENERATOR_TABLE_NAME_PARAM = "generatorTableName"; 136 public static final String ANNOTATION_STRING_DEFAULT = ""; 137 138 153 private AnnotationBinder() {} 154 155 private static final Log log = LogFactory.getLog(AnnotationBinder.class); 156 157 public static void bindPackage(String packageName, ExtendedMappings mappings) { 158 Package pckg = null; 159 try { 160 pckg = ReflectHelper.classForName(packageName + ".package-info").getPackage(); 161 } 162 catch (ClassNotFoundException cnf) { 163 log.warn("Package not found or wo package-info.java: " + packageName); 164 return; 165 } 166 if ( pckg.isAnnotationPresent(SequenceGenerator.class) ) { 167 SequenceGenerator ann = pckg.getAnnotation(SequenceGenerator.class); 168 IdGenerator idGen = buildIdGenerator(ann); 169 mappings.addGenerator(idGen); 170 log.debug("Add sequence generator with name: " + idGen.getName() ); 171 } 172 if ( pckg.isAnnotationPresent(TableGenerator.class) ) { 173 TableGenerator ann = pckg.getAnnotation(TableGenerator.class); 174 IdGenerator idGen = buildIdGenerator(ann); 175 mappings.addGenerator(idGen); 176 177 } 178 if ( pckg.isAnnotationPresent(GeneratedIdTable.class) ) { 179 GeneratedIdTable ann = pckg.getAnnotation(GeneratedIdTable.class); 180 Properties params = buildPropertiesFromGeneratorTable(ann); 181 mappings.addGeneratorTable(ann.name(), params); 182 } 183 if ( pckg.isAnnotationPresent(GenericGenerator.class) ) { 184 GenericGenerator ann = pckg.getAnnotation(GenericGenerator.class); 185 IdGenerator idGen = buildIdGenerator(ann); 186 mappings.addGenerator(idGen); 187 } 188 bindQueries(pckg, mappings); 189 bindFilterDefs(pckg, mappings); 190 bindTypeDefs(pckg, mappings); 191 } 192 193 private static void bindQueries(AnnotatedElement annotatedElement, ExtendedMappings mappings) { 194 { 195 SqlResultSetMapping ann = annotatedElement.getAnnotation(SqlResultSetMapping.class); 196 QueryBinder.bindSqlResultsetMapping(ann, mappings); 197 } 198 { 199 NamedQuery ann = annotatedElement.getAnnotation(NamedQuery.class); 200 QueryBinder.bindQuery(ann, mappings); 201 } 202 { 203 NamedQueries ann = annotatedElement.getAnnotation(NamedQueries.class); 204 QueryBinder.bindQueries(ann, mappings); 205 } 206 { 207 NamedNativeQuery ann = annotatedElement.getAnnotation(NamedNativeQuery.class); 208 QueryBinder.bindNativeQuery(ann, mappings); 209 } 210 { 211 NamedNativeQueries ann = annotatedElement.getAnnotation(NamedNativeQueries.class); 212 QueryBinder.bindNativeQueries(ann, mappings); 213 } 214 } 215 216 private static Properties buildPropertiesFromGeneratorTable(GeneratedIdTable ann) { 217 Properties params = new Properties (); 218 if ( ! isDefault( ann.pkColumnName() ) ) 219 params.setProperty( MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, ann.pkColumnName() ); 220 if ( ! isDefault( ann.valueColumnName() ) ) 221 params.setProperty( MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, ann.valueColumnName() ); 222 if ( ann.table().specified() == true ) { 223 javax.persistence.Table table = ann.table(); 224 if ( ! isDefault( table.name() ) ) 225 params.setProperty( MultipleHiLoPerTableGenerator.ID_TABLE, table.name() ); 226 if ( ! isDefault( table.catalog() ) ) 227 params.setProperty( MultipleHiLoPerTableGenerator.CATALOG, table.catalog() ); 228 if ( ! isDefault( table.schema() ) ) 229 params.setProperty( MultipleHiLoPerTableGenerator.SCHEMA, table.schema() ); 230 } 232 else { 233 params.setProperty( MultipleHiLoPerTableGenerator.ID_TABLE, ann.name() ); 234 } 235 return params; 236 } 237 238 private static IdGenerator buildIdGenerator(java.lang.annotation.Annotation ann) { 239 IdGenerator idGen = new IdGenerator(); 240 if (ann == null) { 241 idGen = null; 242 } 243 else if (ann instanceof TableGenerator) { 244 TableGenerator tabGen = (TableGenerator) ann; 245 idGen.setName( tabGen.name() ); 246 idGen.setIdentifierGeneratorStrategy( MultipleHiLoPerTableGenerator.class.getName() ); 247 if ( !isDefault( tabGen.tableName() ) ) { 248 idGen.addParam( GENERATOR_TABLE_NAME_PARAM, tabGen.tableName() ); 249 } 250 if ( !isDefault( tabGen.pkColumnValue() ) ) { 251 idGen.addParam( MultipleHiLoPerTableGenerator.PK_VALUE_NAME, tabGen.pkColumnValue() ); 252 } 253 idGen.addParam( TableHiLoGenerator.MAX_LO, String.valueOf( tabGen.allocationSize() ) ); 254 log.debug("Add table generator with name: " + idGen.getName() ); 255 } 256 else if (ann instanceof SequenceGenerator) { 257 SequenceGenerator seqGen = (SequenceGenerator) ann; 258 idGen.setName( seqGen.name() ); 259 idGen.setIdentifierGeneratorStrategy("sequence"); 260 261 if (! isDefault( seqGen.sequenceName() ) ) { 262 idGen.addParam( org.hibernate.id.SequenceGenerator.SEQUENCE, seqGen.sequenceName() ); 263 } 264 if (seqGen.initialValue() != 0 || seqGen.allocationSize() != 50) { 266 log.warn("Hibernate does not support SequenceGenerator.initialValue() nor SequenceGenerator.allocationSize()"); 267 } 268 log.debug("Add sequence generator with name: " + idGen.getName() ); 269 } 270 else if (ann instanceof GenericGenerator) { 271 GenericGenerator genGen = (GenericGenerator) ann; 272 idGen.setName( genGen.name() ); 273 idGen.setIdentifierGeneratorStrategy( genGen.strategy() ); 274 Parameter[] params = genGen.parameters(); 275 for ( Parameter parameter : params ) { 276 idGen.addParam( parameter.name(), parameter.value() ); 277 } 278 log.debug("Add generic generator with name: " + idGen.getName() ); 279 } 280 else { 281 throw new AssertionFailure("Unknown Generator annotation: " + ann); 282 } 283 return idGen; 284 } 285 286 290 public static void bindClass(Class clazzToProcess, Map <Class , InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings) throws MappingException { 291 InheritanceState inheritanceState = inheritanceStatePerClass.get(clazzToProcess); 293 AnnotatedClassType classType = mappings.getClassType(clazzToProcess); 294 if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) ) return; if ( AnnotatedClassType.EMBEDDABLE.equals( classType ) ) return; if ( ! classType.equals(AnnotatedClassType.ENTITY) ) { 298 throw new AnnotationException( "Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess.getName() ); 299 } 300 AnnotatedElement annotatedClass = clazzToProcess; 301 bindQueries(annotatedClass, mappings); 302 bindFilterDefs(annotatedClass, mappings); 303 bindTypeDefs(annotatedClass, mappings); 304 Class superClass = clazzToProcess.getSuperclass(); 305 PersistentClass superEntity = mappings.getClass( superClass.getName() ); 306 if (superEntity == null) { 307 if ( inheritanceState.hasParents ) { 309 throw new AnnotationException( "Subclass has to be binded after it's mother class: " 310 + superClass.getName() ); 311 } 312 } 313 String schema = ""; 314 String table = ""; String catalog = ""; 316 String discrimValue = null; 317 List uniqueConstraints = new ArrayList (); 318 Ejb3DiscriminatorColumn discriminatorColumn = null; 319 Ejb3JoinColumn[] inheritanceJoinedColumns = null; 320 321 if (annotatedClass.isAnnotationPresent(javax.persistence.Table.class) ) { 322 javax.persistence.Table tabAnn = annotatedClass.getAnnotation(javax.persistence.Table.class); 323 table = tabAnn.name(); 324 schema = tabAnn.schema(); 325 catalog = tabAnn.catalog(); 326 if (tabAnn.uniqueConstraints().length != 0) { 327 for( UniqueConstraint uc : tabAnn.uniqueConstraints() ) { 328 uniqueConstraints.add( uc.columnNames() ); 329 } 330 } 331 } 332 final boolean hasJoinedColumns = InheritanceType.JOINED.equals( inheritanceState.type ) && inheritanceState.hasParents; 333 if ( hasJoinedColumns ) { 334 PrimaryKeyJoinColumns jcsAnn = annotatedClass.getAnnotation(PrimaryKeyJoinColumns.class); 335 boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0; 336 if (explicitInheritanceJoinedColumns) { 337 int nbrOfInhJoinedColumns = jcsAnn.value().length; 338 PrimaryKeyJoinColumn jcAnn; 339 inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns]; 340 for (int colIndex = 0 ; colIndex < nbrOfInhJoinedColumns ; colIndex++) { 341 jcAnn = jcsAnn.value()[colIndex]; 342 inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn(jcAnn, superEntity.getIdentifier(), 343 (Map <String , Join>) null, (PropertyHolder) null, mappings); 344 } 345 } 346 else { 347 PrimaryKeyJoinColumn jcAnn = annotatedClass.getAnnotation(PrimaryKeyJoinColumn.class); 348 inheritanceJoinedColumns = new Ejb3JoinColumn[1]; 349 inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn(jcAnn, superEntity.getIdentifier(), 350 (Map <String , Join>) null, (PropertyHolder) null, mappings); 351 } 352 log.debug("Joined column(s) created" ); 353 } 354 else { 355 if ( annotatedClass.isAnnotationPresent( javax.persistence.PrimaryKeyJoinColumns.class ) 356 || annotatedClass.isAnnotationPresent( javax.persistence.PrimaryKeyJoinColumn.class )) { 357 log.warn("Root entity should not hold an InheritanceJoinColum(s), will be ignored"); 358 } 359 } 360 361 if ( InheritanceType.SINGLE_TABLE.equals(inheritanceState.type) ) { 362 javax.persistence.Inheritance inhAnn = annotatedClass.getAnnotation(javax.persistence.Inheritance.class); 363 DiscriminatorType discriminatorType = inhAnn == null ? DiscriminatorType.STRING : inhAnn.discriminatorType(); 364 javax.persistence.DiscriminatorColumn discAnn = annotatedClass.getAnnotation(javax.persistence.DiscriminatorColumn.class); 365 org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = annotatedClass.getAnnotation(org.hibernate.annotations.DiscriminatorFormula.class); 366 if ( ! inheritanceState.hasParents) { 367 discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(discriminatorType, discAnn, discFormulaAnn, mappings); 368 } 369 if ( discAnn != null && inheritanceState.hasParents ) { 370 log.warn( 371 "Discriminator column has to be defined in the root entity, it will be ignored in subclass: " 372 + clazzToProcess.getName() 373 ); 374 } 375 discrimValue = inhAnn == null ? null : inhAnn.discriminatorValue(); 376 } 377 378 PersistentClass persistentClass; 380 if ( ! inheritanceState.hasParents ) { 382 persistentClass = new RootClass(); 383 } 384 else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) { 385 persistentClass = new Subclass(superEntity); 386 } 387 else if ( InheritanceType.JOINED.equals( inheritanceState.type ) ) { 388 persistentClass = new JoinedSubclass(superEntity); 389 } 390 else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.type ) ) { 391 persistentClass = new UnionSubclass(superEntity); 392 } 393 else { 394 throw new AssertionFailure("Unknown inheritance type: " + inheritanceState.type); 395 } 396 Proxy proxyAnn = annotatedClass.getAnnotation(Proxy.class); 397 BatchSize sizeAnn = annotatedClass.getAnnotation(BatchSize.class); 398 Where whereAnn = annotatedClass.getAnnotation(Where.class); 399 Entity entityAnn = annotatedClass.getAnnotation(Entity.class); 400 org.hibernate.annotations.Entity hibEntityAnn = annotatedClass.getAnnotation( org.hibernate.annotations.Entity.class ); 401 org.hibernate.annotations.Cache cacheAnn = annotatedClass.getAnnotation( org.hibernate.annotations.Cache.class ); 402 EntityBinder entityBinder = new EntityBinder(entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings); 403 entityBinder.setDiscriminatorValue(discrimValue); 404 entityBinder.setBatchSize(sizeAnn); 405 entityBinder.setProxy(proxyAnn); 406 entityBinder.setWhere(whereAnn); 407 entityBinder.setCache(cacheAnn); 408 entityBinder.setInheritanceState(inheritanceState); 409 Filter filterAnn = annotatedClass.getAnnotation(Filter.class); 410 if (filterAnn != null) { 411 entityBinder.addFilter( filterAnn.name(), filterAnn.condition() ); 412 } 413 Filters filtersAnn = annotatedClass.getAnnotation(Filters.class); 414 if (filtersAnn != null) { 415 for ( Filter filter : filtersAnn.value() ) { 416 entityBinder.addFilter( filter.name(), filter.condition() ); 417 } 418 } 419 entityBinder.bindEntity(); 420 421 if ( inheritanceState.hasTable() ) { 422 Check checkAnn = annotatedClass.getAnnotation(Check.class); 423 String constraints = checkAnn == null ? null : checkAnn.constraints(); 424 entityBinder.bindTable( 425 schema, catalog, table, uniqueConstraints, 426 constraints, inheritanceState.hasDenormalizedTable() ? superEntity.getTable() : null 427 ); 428 } 429 Map <String , Column[]> columnOverride = PropertyHolderBuilder.buildColumnOverride(annotatedClass); 430 PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(persistentClass, columnOverride); 431 432 javax.persistence.SecondaryTable secTabAnn = annotatedClass.getAnnotation(javax.persistence.SecondaryTable.class); 433 javax.persistence.SecondaryTables secTabsAnn = annotatedClass.getAnnotation(javax.persistence.SecondaryTables.class); 434 JoinColumn joinColAnn = annotatedClass.getAnnotation(JoinColumn.class); 435 JoinColumns joinColsAnn = annotatedClass.getAnnotation(JoinColumns.class); 436 entityBinder.firstLevelSecondaryTablesBinding(secTabAnn, secTabsAnn, joinColAnn, joinColsAnn); 437 438 OnDelete onDeleteAnn = annotatedClass.getAnnotation(OnDelete.class); 439 boolean onDeleteAppropriate = false; 440 if ( InheritanceType.JOINED.equals( inheritanceState.type ) && inheritanceState.hasParents ) { 441 onDeleteAppropriate = true; 442 JoinedSubclass jsc = (JoinedSubclass) persistentClass; 443 if ( persistentClass.getEntityPersisterClass()==null ) { 444 persistentClass.getRootClass().setEntityPersisterClass(JoinedSubclassEntityPersister.class); 445 } 446 SimpleValue key = new DependantValue( jsc.getTable(), jsc.getIdentifier() ); 447 jsc.setKey(key); 448 if (onDeleteAnn != null) { 449 key.setCascadeDeleteEnabled( OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) ); 450 } 451 else { 452 key.setCascadeDeleteEnabled(false); 453 } 454 TableBinder.bindFk(jsc, null, inheritanceJoinedColumns, key, false ); 455 jsc.createPrimaryKey(); 456 jsc.createForeignKey(); 457 458 } 459 else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) { 460 if ( inheritanceState.hasParents ) { 461 if ( persistentClass.getEntityPersisterClass() == null) { 462 persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class ); 463 } 464 } 465 else { 466 if ( inheritanceState.hasSons || ! discriminatorColumn.isImplicit() ) { 467 bindDiscriminatorToPersistentClass( 469 (RootClass) persistentClass, 470 discriminatorColumn, 471 entityBinder.getSecondaryTables(), 472 propertyHolder); 473 } 474 } 475 } 476 else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.type ) ) { 477 if ( inheritanceState.hasParents ) { 478 if ( persistentClass.getEntityPersisterClass() == null) { 479 persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class ); 480 } 481 } 482 } 483 if (onDeleteAnn != null && onDeleteAppropriate == false) { 484 log.warn( "Inapropriate use of @OnDelete on entity, annotation ignored: " + propertyHolder.getEntityName() ); 485 } 486 487 HashMap <String , IdGenerator> classGenerators = buildLocalGenerators(annotatedClass); 489 HashMap <String , Properties > classGeneratorTables = buildLocalGeneratorTable(annotatedClass); 490 Set <String > idProperties = new HashSet <String >(); 491 if ( annotatedClass.isAnnotationPresent( IdClass.class ) ) { 492 IdClass idClass = annotatedClass.getAnnotation(IdClass.class); 493 Class compositeClass = idClass.value(); 494 Embeddable embeddableAnn = (Embeddable) compositeClass.getAnnotation(Embeddable.class); 495 boolean isComponent = true; 496 boolean propertyAccess = true; 497 if (embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD) propertyAccess = false; 498 String generatorType = "assigned"; 499 String generator = ANNOTATION_STRING_DEFAULT; 500 PropertyInferredData inferredData = new PropertyInferredData(propertyAccess == true ? "property": "field", "id", compositeClass); 501 HashMap <String , IdGenerator> localGenerators = new HashMap <String , IdGenerator>(); 502 HashMap <String , Properties > localGeneratorTables = new HashMap <String , Properties >(); 503 bindId( 504 generatorType, 505 generator, 506 inferredData, 507 null, 508 propertyHolder, 509 localGenerators, 510 localGeneratorTables, 511 isComponent, 512 columnOverride, 513 propertyAccess, 514 entityBinder, 515 null, 516 true, 517 mappings); 518 inferredData = new PropertyInferredData(propertyAccess == true ? "property": "field", "_identifierMapper", compositeClass); 519 Component mapper = fillComponent( 520 propertyHolder, 521 inferredData, 522 propertyAccess, 523 false, 524 entityBinder, 525 true, 526 columnOverride, 527 mappings); 528 mapper.setEmbedded(true); 529 persistentClass.setIdentifierMapper(mapper); 530 Property property = new Property(); 531 property.setName("_identifierMapper"); 532 property.setNodeName("id"); 533 property.setUpdateable(false); 534 property.setInsertable(false); 535 property.setValue(mapper); 536 property.setPropertyAccessorName( "embedded" ); 537 persistentClass.addProperty(property); 538 entityBinder.setIgnoreIdAnnotations(true); 539 540 Iterator properties = mapper.getPropertyIterator(); 541 while ( properties.hasNext() ) { 542 idProperties.add( ( (Property) properties.next() ).getName() ); 543 } 544 } 545 546 List <Class > classesToProcess = orderClassesToBeProcessed(clazzToProcess, inheritanceStatePerClass, inheritanceState); 548 int deep = classesToProcess.size(); 549 List <PropertyAnnotatedElement> elements = new ArrayList <PropertyAnnotatedElement>(); 550 boolean hasIdentifier = false; 551 for ( int index = 0 ; index < deep ; index++ ) { 552 Class clazz = classesToProcess.get(index); 553 InheritanceState state = inheritanceStatePerClass.get(clazz); 554 boolean isPropertyAccess; 555 if (state.isEmbeddableSuperclass) { 557 isPropertyAccess = state.accessType == AccessType.PROPERTY; 558 } 559 else { 560 isPropertyAccess = entityBinder.isPropertyAccess(); 561 } 562 boolean currentHasIdentifier = addElementsOfAClass(elements, propertyHolder, isPropertyAccess, clazz); 563 hasIdentifier = hasIdentifier || currentHasIdentifier; 564 } 565 final boolean rootEntityWoId = !entityBinder.isIgnoreIdAnnotations() && !hasIdentifier && !inheritanceState.hasParents; 566 final boolean subclassAndSingleTableStrategy = inheritanceState.type == InheritanceType.SINGLE_TABLE 567 && inheritanceState.hasParents; 568 if (rootEntityWoId) { 569 throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() ); 570 } 571 Set <String > missingIdProperties = new HashSet <String >(idProperties); 572 for (PropertyAnnotatedElement propertyAnnotatedElement : elements) { 573 String propertyName = propertyAnnotatedElement.inferredData.getPropertyName(); 574 if ( ! idProperties.contains( propertyName ) ) { 575 processElementAnnotations(propertyHolder, 576 subclassAndSingleTableStrategy ? Nullability.FORCED_NULL : Nullability.NO_CONSTRAINT, 577 propertyAnnotatedElement.element, 578 propertyAnnotatedElement.inferredData, classGenerators, classGeneratorTables, entityBinder, false, mappings); 579 } 580 else { 581 missingIdProperties.remove(propertyName); 582 } 583 } 584 585 if (missingIdProperties.size() != 0) { 586 StringBuffer missings = new StringBuffer (); 587 for(String property : missingIdProperties) { 588 missings.append(property).append(", "); 589 } 590 throw new AnnotationException("Unable to find properties (" 591 + missings.substring(0, missings.length() - 2) 592 + ") in entity annotated with @IdClass:" + persistentClass.getEntityName() ); 593 } 594 595 if ( ! inheritanceState.hasParents ) { 596 ( (RootClass) persistentClass).createPrimaryKey(); 597 } 598 else { 599 superEntity.addSubclass( (Subclass) persistentClass ); 600 } 601 602 mappings.addClass(persistentClass); 603 entityBinder.finalSecondaryTableBinding(propertyHolder); 604 605 entityBinder.addIndexes( annotatedClass.getAnnotation( org.hibernate.annotations.Table.class ) ); 607 entityBinder.addIndexes( annotatedClass.getAnnotation( org.hibernate.annotations.Tables.class ) ); 608 609 ResourceBundle rb = null; 611 new ClassValidator( clazzToProcess, rb ).apply( persistentClass ); 614 } 615 616 private static List <Class > orderClassesToBeProcessed( 617 Class annotatedClass, Map <Class , InheritanceState> inheritanceStatePerClass, 618 InheritanceState inheritanceState 619 ) { 620 List <Class > classesToProcess = new ArrayList <Class >(); 622 Class currentClassInHierarchy = annotatedClass; 623 InheritanceState superclassState; 624 do { 625 classesToProcess.add(0, currentClassInHierarchy); 626 currentClassInHierarchy = currentClassInHierarchy.getSuperclass(); 627 superclassState = inheritanceStatePerClass.get( currentClassInHierarchy ); 628 } 629 while (! inheritanceState.hasParents && superclassState != null); 630 return classesToProcess; 631 } 632 633 private static void bindFilterDefs(AnnotatedElement annotatedElement, ExtendedMappings mappings) { 634 FilterDef defAnn = annotatedElement.getAnnotation(FilterDef.class); 635 FilterDefs defsAnn = annotatedElement.getAnnotation(FilterDefs.class); 636 if (defAnn != null) { 637 bindFilterDef(defAnn, mappings); 638 } 639 if (defsAnn != null) { 640 for ( FilterDef def : defsAnn.value() ) { 641 bindFilterDef(def, mappings); 642 } 643 } 644 } 645 646 private static void bindFilterDef(FilterDef defAnn, ExtendedMappings mappings) { 647 FilterDefinition def = new FilterDefinition( defAnn.name() ); 648 for ( ParamDef param : defAnn.parameters() ) { 649 TypeFactory.heuristicType( param.type() ); 650 def.addParameterType( param.name(), TypeFactory.heuristicType( param.type() ) ); 651 } 652 mappings.addFilterDefinition(def); 653 } 654 655 private static void bindTypeDefs(AnnotatedElement annotatedElement, ExtendedMappings mappings) { 656 TypeDef defAnn = annotatedElement.getAnnotation(TypeDef.class); 657 TypeDefs defsAnn = annotatedElement.getAnnotation(TypeDefs.class); 658 if (defAnn != null) { 659 bindTypeDef(defAnn, mappings); 660 } 661 if (defsAnn != null) { 662 for ( TypeDef def : defsAnn.value() ) { 663 bindTypeDef(def, mappings); 664 } 665 } 666 } 667 668 private static void bindTypeDef(TypeDef defAnn, ExtendedMappings mappings) { 669 Properties params = new Properties (); 670 for ( Parameter param : defAnn.parameters() ) { 671 params.setProperty( param.name(), param.value() ); 672 } 673 mappings.addTypeDef( defAnn.name(), defAnn.typeClass().getName(), params ); 674 } 675 676 private static HashMap <String , Properties > buildLocalGeneratorTable(AnnotatedElement annotatedClass) { 677 HashMap <String , Properties > result = new HashMap <String , Properties >(); 678 GeneratedIdTable ann = (GeneratedIdTable) annotatedClass.getAnnotation(GeneratedIdTable.class); 679 if (ann != null) { 680 result.put( ann.name(), buildPropertiesFromGeneratorTable(ann) ); 681 } 682 return result; 683 } 684 685 private static void bindDiscriminatorToPersistentClass( 686 RootClass rootClass, 687 Ejb3DiscriminatorColumn discriminatorColumn, Map <String , Join> secondaryTables, 688 PropertyHolder propertyHolder 689 ) { 690 if (rootClass.getDiscriminator() == null) { 691 if (discriminatorColumn == null) { 692 throw new AssertionFailure("discriminator column should have been built"); 693 } 694 discriminatorColumn.setJoins(secondaryTables); 695 discriminatorColumn.setPropertyHolder(propertyHolder); 696 SimpleValue discrim = new SimpleValue( rootClass.getTable() ); 697 rootClass.setDiscriminator(discrim); 698 discriminatorColumn.linkWithValue(discrim); 699 discrim.setTypeName(discriminatorColumn.getDiscriminatorTypeName()); 700 rootClass.setPolymorphic(true); 701 log.debug( "Setting discriminator for entity " + rootClass.getEntityName() ); 702 } 703 } 704 705 708 private static boolean addElementsOfAClass( 709 List <PropertyAnnotatedElement> elements, PropertyHolder propertyHolder, boolean propertyAccess, 710 final Class annotatedClass 711 ) { 712 boolean hasIdentifier = false; 713 if (propertyAccess) { 714 log.debug("Processing " + propertyHolder.getEntityName() + " per property access"); 715 Method [] methods = annotatedClass.getDeclaredMethods(); 716 AnnotatedElement currentElt; 717 int index = 0; 718 while( index < methods.length) { 719 currentElt = (AnnotatedElement ) methods[index]; 720 final boolean currentHasIdentifier = addAnnotatedElement(currentElt, elements); 721 hasIdentifier = hasIdentifier || currentHasIdentifier; 722 index++; 723 } 724 } 725 else { 726 log.debug("Processing " + propertyHolder.getEntityName() + " per field access"); 727 Field [] fields = annotatedClass.getDeclaredFields(); 728 AnnotatedElement currentElt; 729 int index = 0; 730 while( index < fields.length) { 731 currentElt = (AnnotatedElement ) fields[index]; 732 final boolean currentHasIdentifier = addAnnotatedElement(currentElt, elements); 733 hasIdentifier = hasIdentifier || currentHasIdentifier; 734 index++; 735 } 736 } 737 return hasIdentifier; 738 } 739 740 private static boolean addAnnotatedElement(AnnotatedElement elt, List <PropertyAnnotatedElement> annElts) { 741 boolean hasIdentifier = false; 742 PropertyAnnotatedElement propertyAnnotatedElement = new PropertyAnnotatedElement(elt); 743 if ( ! propertyAnnotatedElement.inferredData.skip() ) { 744 748 final AnnotatedElement element = propertyAnnotatedElement.element; 749 if ( element.isAnnotationPresent(Id.class) || element.isAnnotationPresent(EmbeddedId.class) ) { 750 annElts.add(0, propertyAnnotatedElement); 751 hasIdentifier = true; 752 } 753 else { 754 annElts.add(propertyAnnotatedElement); 755 hasIdentifier = false; 756 } 757 } 758 return hasIdentifier; 759 } 760 761 764 private static void processElementAnnotations( 765 PropertyHolder propertyHolder, Nullability nullability, AnnotatedElement annotatedElt, 766 PropertyInferredData inferredData, HashMap <String , IdGenerator> classGenerators, 767 HashMap <String , Properties > classGeneratorTables, EntityBinder entityBinder, boolean isIdentifierMapper, 768 ExtendedMappings mappings 769 ) 770 throws MappingException { 771 Ejb3Column[] columns = null; 772 if ( annotatedElt.isAnnotationPresent(Transient.class) ) { 773 return; 774 } 775 if ( log.isDebugEnabled() ) { 776 log.debug( "Processing annotations of " + propertyHolder.getEntityName() + "." + inferredData.getPropertyName() ); 777 } 778 if ( annotatedElt.isAnnotationPresent(Column.class) || annotatedElt.isAnnotationPresent(Formula.class) ) { 779 Column ann = (Column) annotatedElt.getAnnotation(Column.class); 780 Formula formulaAnn = (Formula) annotatedElt.getAnnotation(Formula.class); 781 columns = Ejb3Column.buildColumnFromAnnotation(new Column[] { ann }, formulaAnn, nullability, propertyHolder, inferredData, entityBinder.getSecondaryTables(), mappings); 782 columns[0].addIndex( annotatedElt.getAnnotation( Index.class ) ); 783 } 784 else if ( annotatedElt.isAnnotationPresent(Columns.class) ) { 785 Columns anns = annotatedElt.getAnnotation(Columns.class); 786 columns = Ejb3Column.buildColumnFromAnnotation(anns.columns(), null, nullability, propertyHolder, inferredData, entityBinder.getSecondaryTables(), mappings); 787 } 788 else if ( annotatedElt.isAnnotationPresent(JoinColumn.class) ) { 789 JoinColumn ann = (JoinColumn) annotatedElt.getAnnotation(JoinColumn.class); 790 columns = new Ejb3JoinColumn[1]; 791 columns[0] = Ejb3JoinColumn.buildJoinColumn(ann, 792 entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappings); 793 } 794 else if ( annotatedElt.isAnnotationPresent(JoinColumns.class) ) { 795 JoinColumns ann = annotatedElt.getAnnotation(JoinColumns.class); 796 JoinColumn[] annColumns = ann.value(); 797 int length = annColumns.length; 798 if (length == 0) { 799 throw new AnnotationException("Cannot bind an empty @JoinColumns"); 800 } 801 columns = new Ejb3JoinColumn[length]; 802 for (int index = 0 ; index < length ; index++) { 803 columns[index] = Ejb3JoinColumn.buildJoinColumn(annColumns[index], 804 entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappings); 805 } 806 } 807 else { 808 if ( annotatedElt.isAnnotationPresent(ManyToOne.class) 809 || annotatedElt.isAnnotationPresent(OneToOne.class) ) { 810 columns = new Ejb3JoinColumn[1]; 811 if ( annotatedElt.isAnnotationPresent(JoinTable.class) ) { 812 JoinTable assocTable = annotatedElt.getAnnotation(JoinTable.class); 813 throw new NotYetImplementedException("association table on a single ended association is not yet supported"); 815 } 816 else { 817 columns[0] = Ejb3JoinColumn.buildImplicitJoinColumn( (String ) null, entityBinder.getSecondaryTables(), 818 propertyHolder, inferredData.getPropertyName(), mappings); 819 } 820 } 821 else if ( annotatedElt.isAnnotationPresent(OneToMany.class) ) { 822 columns = new Ejb3JoinColumn[1]; 823 String mappedBy = ( (OneToMany) annotatedElt.getAnnotation(OneToMany.class) ).mappedBy(); 824 columns[0] = Ejb3JoinColumn.buildImplicitJoinColumn(mappedBy, entityBinder.getSecondaryTables(), 825 propertyHolder, inferredData.getPropertyName(), mappings); 826 } 827 else { 828 columns = Ejb3Column.buildColumnFromAnnotation(null, null, nullability, propertyHolder, inferredData, entityBinder.getSecondaryTables(), mappings); 829 } 830 } 831 if (nullability == Nullability.FORCED_NOT_NULL) { 832 for (Ejb3Column col : columns) { 834 col.forceNotNull(); 835 } 836 } 837 838 final Class returnedClass = inferredData.getReturnedClassOrElement(); 839 if ( !entityBinder.isIgnoreIdAnnotations() && 840 (annotatedElt.isAnnotationPresent(Id.class) || annotatedElt.isAnnotationPresent(EmbeddedId.class) ) ) { 841 if (isIdentifierMapper) throw new AnnotationException("@IdClass class should not have @Id nor @EmbeddedId proeperties"); 842 log.debug(inferredData.getPropertyName() + " is an id"); 843 Id idAnn = (Id) annotatedElt.getAnnotation(Id.class); 844 EmbeddedId embeddedId = (EmbeddedId) annotatedElt.getAnnotation(EmbeddedId.class); 845 846 HashMap <String , IdGenerator> localGenerators = (HashMap <String , IdGenerator>) classGenerators.clone(); 848 HashMap <String , Properties > localGeneratorTables = (HashMap <String , Properties >) classGeneratorTables.clone(); 849 localGenerators.putAll( buildLocalGenerators(annotatedElt) ); 850 localGeneratorTables.putAll( buildLocalGeneratorTable(annotatedElt) ); 851 852 Embeddable embeddableAnn = (Embeddable) returnedClass.getAnnotation(Embeddable.class); 854 Map <String , Column[]> columnOverride = PropertyHolderBuilder.buildColumnOverride(annotatedElt); 855 final boolean isComponent = embeddableAnn != null || embeddedId != null; 857 boolean propertyAccess = true; 858 if (isComponent && embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD) propertyAccess = false; 859 String generatorType = idAnn != null ? generatorType( idAnn.generate() ) : "assigned"; 861 String generator = idAnn != null ? idAnn.generator() : ANNOTATION_STRING_DEFAULT; 862 Type typeAnn = annotatedElt.getAnnotation(Type.class); 863 bindId( 864 generatorType, 865 generator, 866 inferredData, 867 columns[0], 868 propertyHolder, 869 localGenerators, 870 localGeneratorTables, 871 isComponent, 872 columnOverride, 873 propertyAccess, 874 entityBinder, 875 typeAnn, 876 false, 877 mappings); 878 if ( log.isDebugEnabled() ) { 879 log.debug("Bind " + (isComponent ? "@Id":"@EmbeddedId") + " on " + inferredData.getPropertyName() ); 880 } 881 } 882 else if ( annotatedElt.isAnnotationPresent(Version.class) ) { 883 if (isIdentifierMapper) throw new AnnotationException("@IdClass class should not have @Version proeperty"); 884 if ( ! ( propertyHolder.getPersistentClass() instanceof RootClass ) ) { 885 throw new AnnotationException( 886 "Unable to define/override @Version on a subclass: " 887 + propertyHolder.getEntityName() ); 888 } 889 log.debug(inferredData.getPropertyName() + " is a version property"); 890 RootClass rootClass = (RootClass) propertyHolder.getPersistentClass(); 891 boolean lazy = false; 892 Type annType = (Type) annotatedElt.getAnnotation(Type.class); 894 PropertyBinder propBinder = new PropertyBinder(); 895 propBinder.setName( inferredData.getPropertyName() ); 896 propBinder.setReturnedClassName( inferredData.getReturnedClassName() ); 897 propBinder.setLazy( lazy ); 898 propBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); 899 propBinder.setColumns( columns ); 900 propBinder.setHolder( propertyHolder ); propBinder.setExplicitType(annType); 902 propBinder.setMappings(mappings); 903 Property prop = propBinder.bind(); 904 rootClass.setVersion(prop); 905 SimpleValue simpleValue = (SimpleValue) prop.getValue(); 906 if ( !simpleValue.isTypeSpecified() ) simpleValue.setTypeName("integer"); 907 simpleValue.setNullValue("undefined"); 908 rootClass.setOptimisticLockMode(Versioning.OPTIMISTIC_LOCK_VERSION); 909 log.debug( "Version name: " + rootClass.getVersion().getName() + ", unsavedValue: " + ( (SimpleValue) rootClass.getVersion().getValue() ).getNullValue() ); 910 } 911 else if ( annotatedElt.isAnnotationPresent(ManyToOne.class) ) { 912 ManyToOne ann = annotatedElt.getAnnotation(ManyToOne.class); 913 Cascade hibernateCascade = annotatedElt.getAnnotation(Cascade.class); 914 Ejb3JoinColumn.checkIfJoinColumn(columns, propertyHolder, inferredData); 915 bindManyToOne( getCascadeStrategy( ann.cascade(), hibernateCascade ), 916 (Ejb3JoinColumn[]) columns, 917 ann.optional(), 918 getFetchMode( ann.fetch() ), 919 inferredData.getPropertyName(), 920 inferredData.getReturnedClassOrElementName(), 921 ann.targetEntity(), 922 inferredData.getDefaultAccess(), 923 propertyHolder, 924 false, isIdentifierMapper, mappings 925 ); 926 } 927 else if ( annotatedElt.isAnnotationPresent(OneToOne.class) ) { 928 OneToOne ann = annotatedElt.getAnnotation(OneToOne.class); 929 boolean trueOneToOne = annotatedElt.isAnnotationPresent(PrimaryKeyJoinColumn.class); 930 Cascade hibernateCascade = annotatedElt.getAnnotation(Cascade.class); 931 Ejb3JoinColumn.checkIfJoinColumn(columns, propertyHolder, inferredData); 932 bindOneToOne( getCascadeStrategy( ann.cascade(), hibernateCascade ), 933 (Ejb3JoinColumn[]) columns, 934 ann.optional(), 935 getFetchMode( ann.fetch() ), 936 inferredData.getPropertyName(), 937 inferredData.getReturnedClassName(), 938 ann.targetEntity(), 939 inferredData.getDefaultAccess(), 940 propertyHolder, 941 ann.mappedBy(), trueOneToOne, isIdentifierMapper, mappings); 942 } 943 else if ( annotatedElt.isAnnotationPresent( OneToMany.class ) 944 || annotatedElt.isAnnotationPresent( ManyToMany.class ) ) { 945 OneToMany oneToManyAnn = annotatedElt.getAnnotation(OneToMany.class); 946 ManyToMany manyToManyAnn = annotatedElt.getAnnotation(ManyToMany.class); 947 org.hibernate.annotations.IndexColumn indexAnn = annotatedElt.getAnnotation( 948 org.hibernate.annotations.IndexColumn.class 949 ); 950 JoinTable assocTable = annotatedElt.getAnnotation(JoinTable.class); 951 boolean isForeignKey = 952 oneToManyAnn != null 953 && assocTable == null 954 && ( ( columns[0].isImplicit() && ! isDefault( oneToManyAnn.mappedBy() ) ) 955 || ! columns[0].isImplicit() 956 ); 957 IndexColumn indexColumn = IndexColumn.buildColumnFromAnnotation( indexAnn, propertyHolder, inferredData, mappings); 958 CollectionBinder collectionBinder = CollectionBinder.getCollectionBinder( 959 propertyHolder.getEntityName(), 960 inferredData, 961 ! indexColumn.isImplicit() 962 ); 963 collectionBinder.setIndexColumn(indexColumn); 964 MapKey mapKeyAnn = annotatedElt.getAnnotation(MapKey.class); 965 collectionBinder.setMapKey(mapKeyAnn); 966 collectionBinder.setPropertyName( inferredData.getPropertyName() ); 967 BatchSize batchAnn = annotatedElt.getAnnotation( BatchSize.class ); 968 collectionBinder.setBatchSize(batchAnn); 969 javax.persistence.OrderBy ejb3OrderByAnn = annotatedElt.getAnnotation( javax.persistence.OrderBy.class ); 970 OrderBy orderByAnn = annotatedElt.getAnnotation( OrderBy.class ); 971 collectionBinder.setEjb3OrderBy(ejb3OrderByAnn); 972 collectionBinder.setSqlOrderBy(orderByAnn); 973 Sort sortAnn = annotatedElt.getAnnotation( Sort.class ); 974 collectionBinder.setSort(sortAnn); 975 Cache cachAnn = annotatedElt.getAnnotation( Cache.class ); 976 collectionBinder.setCache(cachAnn); 977 Filter filterAnn = annotatedElt.getAnnotation(Filter.class); 978 if (filterAnn != null) { 979 collectionBinder.addFilter( filterAnn.name(), filterAnn.condition() ); 980 } 981 Filters filtersAnn = annotatedElt.getAnnotation(Filters.class); 982 if (filtersAnn != null) { 983 for ( Filter filter : filtersAnn.value() ) { 984 collectionBinder.addFilter( filter.name(), filter.condition() ); 985 } 986 } 987 collectionBinder.setPropertyHolder(propertyHolder); 988 Where whereAnn = annotatedElt.getAnnotation( Where.class ); 989 collectionBinder.setWhere(whereAnn); 990 Cascade hibernateCascade = annotatedElt.getAnnotation(Cascade.class); 991 collectionBinder.setCollectionType( inferredData.getCollectionType() ); 992 collectionBinder.setMappings(mappings); 993 collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); 994 if (oneToManyAnn != null && manyToManyAnn != null) { 995 throw new AnnotationException( "@OneToMany and @ManyToMany on the same property is not allowed: " 996 + propertyHolder.getEntityName() + "." + inferredData.getPropertyName() ); 997 } 998 String mappedBy = null; 999 if (oneToManyAnn != null) { 1000 Ejb3JoinColumn.checkIfJoinColumn(columns, propertyHolder, inferredData); 1001 for (Ejb3JoinColumn column : ( Ejb3JoinColumn[] ) columns) { 1002 if ( column.isSecondary() ) { 1003 throw new NotYetImplementedException("Collections having FK in secondary table"); 1004 } 1005 } 1006 collectionBinder.setJoinColumns( ( Ejb3JoinColumn[] ) columns ); 1007 mappedBy = oneToManyAnn.mappedBy(); 1008 collectionBinder.setUnique(true); 1009 collectionBinder.setTargetEntity( oneToManyAnn.targetEntity() ); 1010 collectionBinder.setFetchType( oneToManyAnn.fetch() ); 1011 collectionBinder.setCascadeStrategy( getCascadeStrategy( oneToManyAnn.cascade(), hibernateCascade ) ); 1012 } 1013 else if (manyToManyAnn != null) { 1014 mappedBy = manyToManyAnn.mappedBy(); 1015 collectionBinder.setUnique(false); 1016 collectionBinder.setTargetEntity( manyToManyAnn.targetEntity() ); 1017 collectionBinder.setFetchType( manyToManyAnn.fetch() ); 1018 collectionBinder.setCascadeStrategy( getCascadeStrategy( manyToManyAnn.cascade(), hibernateCascade ) ); 1019 } 1020 collectionBinder.setMappedBy( mappedBy ); 1021 if (isForeignKey) { 1022 for (Ejb3JoinColumn column : ( Ejb3JoinColumn[] ) columns) { 1023 if ( column.isSecondary() ) { 1024 throw new NotYetImplementedException("Collections having FK in secondary table"); 1025 } 1026 } 1027 collectionBinder.setOneToMany(true); 1028 } 1029 else { 1030 collectionBinder.setOneToMany(false); 1031 bindJoinedTableAssociation(assocTable, mappings, entityBinder, collectionBinder, propertyHolder, inferredData, mappedBy); 1032 } 1033 OnDelete onDeleteAnn = annotatedElt.getAnnotation(OnDelete.class); 1034 boolean onDeleteCascade = onDeleteAnn != null ? OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) : false; 1035 collectionBinder.setCascadeDeleteEnabled(onDeleteCascade); 1036 if (isIdentifierMapper) { 1037 collectionBinder.setInsertable(false); 1038 collectionBinder.setUpdatable(false); 1039 } 1040 collectionBinder.bind(); 1041 } 1042 else { 1043 boolean isComponent = false; 1045 Embeddable embeddableAnn = (Embeddable) returnedClass.getAnnotation(Embeddable.class); 1046 Embedded embeddedAnn = (Embedded) annotatedElt.getAnnotation(Embedded.class); 1047 if (embeddedAnn != null || embeddableAnn != null) isComponent = true; 1048 1049 if (isComponent) { 1050 boolean propertyAccess = true; 1052 if (embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD) propertyAccess = false; 1053 Map <String , Column[]> columnOverride = PropertyHolderBuilder.buildColumnOverride(annotatedElt); 1054 bindComponent(inferredData, propertyHolder, propertyAccess, entityBinder, isIdentifierMapper, columnOverride, mappings); 1055 } 1056 else { 1057 Properties typeParameters = null; 1059 boolean lazy = false; 1060 String type = ANNOTATION_STRING_DEFAULT; 1061 if ( annotatedElt.isAnnotationPresent(Basic.class) ) { 1062 Basic ann = (Basic) annotatedElt.getAnnotation(Basic.class); 1063 if (ann.optional() == false && nullability != Nullability.FORCED_NULL) { 1064 for (Ejb3Column col : columns) { 1066 col.forceNotNull(); 1067 } 1068 } 1069 lazy = ann.fetch() == FetchType.LAZY; 1070 switch ( ann.temporalType() ) { 1071 case DATE: type = "date"; break; 1072 case TIME: type = "time"; break; 1073 case TIMESTAMP: type = "timestamp"; break; 1074 case NONE: break; 1075 default: throw new AssertionFailure( "Unknown temporal tyme: " + ann.temporalType() ); 1076 } 1077 } 1078 else if ( annotatedElt.isAnnotationPresent(Lob.class) ) { 1079 Lob lob = annotatedElt.getAnnotation(Lob.class); 1080 if (lob.optional() == false && nullability != Nullability.FORCED_NULL) { 1081 for (Ejb3Column col : columns) { 1083 col.forceNotNull(); 1084 } 1085 } 1086 lazy = lob.fetch() == FetchType.LAZY; 1087 LobType lobType = lob.type(); 1088 if ( LobType.CLOB.equals(lobType) ) { 1089 if ( String .class.equals( returnedClass ) ) { 1090 type = StringClobType.class.getName(); 1091 } 1092 else if (Character .class.equals( returnedClass ) && inferredData.isArray() ) { 1093 type = CharacterArrayClobType.class.getName(); 1094 } 1095 else if (char.class.equals( returnedClass ) && inferredData.isArray() ) { 1096 type = PrimitiveCharacterArrayClobType.class.getName(); 1097 } 1098 else { 1099 type = "clob"; 1100 } 1101 } 1102 if ( LobType.BLOB.equals(lobType ) ) { 1103 if (Byte .class.equals( returnedClass ) && inferredData.isArray() ) { 1104 type = ByteArrayBlobType.class.getName(); 1105 } 1106 else if (byte.class.equals( returnedClass ) && inferredData.isArray() ) { 1107 type = PrimitiveByteArrayBlobType.class.getName(); 1108 } 1109 else if ( returnedClass instanceof Serializable ) { 1110 type = SerializableToBlobType.class.getName(); 1111 typeParameters = new Properties (); 1112 typeParameters.setProperty( 1113 SerializableToBlobType.CLASS_NAME, 1114 returnedClass.getName() 1115 ); 1116 } 1117 else { 1118 type = "blob"; 1119 } 1120 } 1121 } 1122 else if (java.sql.Clob .class.equals( returnedClass ) ) { 1123 type = "clob"; 1124 } 1125 else if (java.sql.Blob .class.equals( returnedClass ) ) { 1126 type = "blob"; 1127 } 1128 1130 if ( ANNOTATION_STRING_DEFAULT.equals(type) ) { 1131 if ( returnedClass.isEnum() ) { 1132 type = EnumType.class.getName(); 1133 typeParameters = new Properties (); 1134 typeParameters.setProperty(EnumType.ENUM, returnedClass.getName() ); 1135 String schema = columns[0].getTable().getSchema(); 1136 schema = schema == null ? "" : schema; 1137 String catalog = columns[0].getTable().getCatalog(); 1138 catalog = catalog == null ? "" : catalog; 1139 typeParameters.setProperty( EnumType.SCHEMA, schema ); 1140 typeParameters.setProperty( EnumType.CATALOG, catalog ); 1141 typeParameters.setProperty( EnumType.TABLE, columns[0].getTable().getName() ); 1142 typeParameters.setProperty( EnumType.COLUMN, columns[0].getName() ); 1143 } 1144 } 1145 1146 Type annType = (Type) annotatedElt.getAnnotation(Type.class); 1147 PropertyBinder propBinder = new PropertyBinder(); 1148 propBinder.setName( inferredData.getPropertyName() ); 1149 propBinder.setReturnedClassName( inferredData.getReturnedClassName() ); 1150 propBinder.setLazy( lazy ); 1151 propBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); 1152 propBinder.setColumns( columns ); 1153 propBinder.setHolder( propertyHolder ); 1154 propBinder.setExplicitType(annType); 1155 propBinder.setExplicitType(type); 1156 propBinder.setTypeParameters(typeParameters); 1157 propBinder.setMappings(mappings); 1158 if (isIdentifierMapper) { 1159 propBinder.setInsertable(false); 1160 propBinder.setUpdatable(false); 1161 } 1162 propBinder.bind(); 1163 } 1164 } 1165 } 1166 1167 private static void bindJoinedTableAssociation(JoinTable joinTableAnn, ExtendedMappings mappings, EntityBinder entityBinder, CollectionBinder collectionBinder, PropertyHolder propertyHolder, PropertyInferredData inferredData, String mappedBy) { 1168 Table assocTable; 1169 JoinColumn[] annJoins; 1170 JoinColumn[] annInverseJoins; 1171 if ( joinTableAnn != null ) { 1172 if (! joinTableAnn.table().specified() ) { 1173 assocTable = null; 1174 } 1175 else { 1176 assocTable = TableBinder.fillTable(joinTableAnn.table().schema(), 1177 joinTableAnn.table().catalog(), 1178 mappings.getNamingStrategy().tableName( joinTableAnn.table().name() ), 1179 false, new ArrayList (), null, null, mappings); 1180 } 1181 1183 JoinColumn[] joins = joinTableAnn.joinColumns(); 1184 1185 if (joins.length == 0) { 1186 annJoins = null; 1187 } 1188 else { 1189 annJoins = joins; 1190 } 1191 1192 JoinColumn[] inverseJoins = joinTableAnn.inverseJoinColumns(); 1193 1194 if (inverseJoins.length == 0) { 1195 annInverseJoins = null; 1196 } 1197 else { 1198 annInverseJoins = inverseJoins; 1199 } 1200 } 1201 else { 1202 assocTable = null; 1203 annJoins = null; 1204 annInverseJoins = null; 1205 } 1206 Ejb3JoinColumn[] joinColumns = buildJoinTableJoinColumns( annJoins, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappedBy, mappings); 1207 Ejb3JoinColumn[] inverseJoinColumns = buildJoinTableJoinColumns( annInverseJoins, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappedBy, mappings); 1208 collectionBinder.setTable(assocTable); 1209 collectionBinder.setJoinColumns(joinColumns); 1210 collectionBinder.setInverseJoinColumns(inverseJoinColumns); 1211 } 1212 1213 private static Ejb3JoinColumn[] buildJoinTableJoinColumns(JoinColumn[] annJoins, Map <String , Join> secondaryTables, 1214 PropertyHolder propertyHolder, String propertyName, String mappedBy, ExtendedMappings mappings) { 1215 Ejb3JoinColumn[] joinColumns; 1216 if (annJoins == null) { 1217 Ejb3JoinColumn currentJoinColumn = new Ejb3JoinColumn(); 1218 currentJoinColumn.setImplicit(true); 1219 currentJoinColumn.setNullable(false); currentJoinColumn.setPropertyHolder(propertyHolder); 1221 currentJoinColumn.setJoins(secondaryTables); 1222 currentJoinColumn.setMappings(mappings); 1223 currentJoinColumn.setPropertyName(propertyName); 1224 currentJoinColumn.setMappedBy(mappedBy); 1225 currentJoinColumn.bind(); 1226 1227 joinColumns = new Ejb3JoinColumn[] { 1228 currentJoinColumn 1229 1230 }; 1231 } 1232 else { 1233 joinColumns = new Ejb3JoinColumn[annJoins.length]; 1234 JoinColumn annJoin; 1235 int length = annJoins.length; 1236 for (int index = 0 ; index < length ; index++) { 1237 annJoin = annJoins[index]; 1238 Ejb3JoinColumn currentJoinColumn = new Ejb3JoinColumn(); 1239 currentJoinColumn.setImplicit(true); 1240 currentJoinColumn.setPropertyHolder(propertyHolder); 1241 currentJoinColumn.setJoins(secondaryTables); 1242 currentJoinColumn.setMappings(mappings); 1243 currentJoinColumn.setPropertyName(propertyName); 1244 currentJoinColumn.setMappedBy(mappedBy); 1245 currentJoinColumn.setJoinAnnotation(annJoin, propertyName); 1246 currentJoinColumn.setNullable(false); currentJoinColumn.bind(); 1249 joinColumns[index] = currentJoinColumn; 1250 } 1251 } 1252 return joinColumns; 1253 } 1254 1255 private static void bindComponent( 1256 PropertyInferredData inferredData, 1257 PropertyHolder propertyHolder, 1258 boolean propertyAccess, 1259 EntityBinder entityBinder, 1260 boolean isIdentifierMapper, Map <String , Column[]> columnOverride, 1261 ExtendedMappings mappings 1262 ) { 1263 Component comp = fillComponent(propertyHolder, inferredData, propertyAccess, true, entityBinder, isIdentifierMapper, columnOverride, mappings); 1264 1265 PropertyBinder binder = new PropertyBinder(); 1266 binder.setName( inferredData.getPropertyName() ); 1267 binder.setValue(comp); 1268 binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); 1269 Property prop = binder.make(); 1270 propertyHolder.addProperty(prop); 1271 } 1272 1273 public static Component fillComponent( 1274 PropertyHolder propertyHolder, PropertyInferredData inferredData, 1275 boolean propertyAccess, boolean isNullable, EntityBinder entityBinder, 1276 boolean isIdentifierMapper, Map <String , Column[]> columnOverride, ExtendedMappings mappings 1277 ) { 1278 Component comp = new Component( propertyHolder.getPersistentClass() ); 1279 if ( !isIdentifierMapper ) { 1280 comp.setComponentClassName( inferredData.getReturnedClassName() ); 1281 } 1282 else { 1283 comp.setComponentClassName( comp.getOwner().getClassName() ); 1284 } 1285 String subpath = StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() ); 1286 log.debug("Binding component with path: " + subpath); 1287 Map <String , Column[]> localColumnOverride = propertyHolder.mergeOverridenColumns(columnOverride); 1288 PropertyHolder subHolder = PropertyHolderBuilder.buildPropertyHolder(comp, subpath, localColumnOverride); 1289 List <PropertyAnnotatedElement> classElements = new ArrayList <PropertyAnnotatedElement>(); 1290 addElementsOfAClass(classElements, 1291 subHolder, 1292 propertyAccess, 1293 inferredData.getReturnedClass() ); 1294 for (PropertyAnnotatedElement propertyAnnotatedElement : classElements) { 1295 processElementAnnotations(subHolder, isNullable == true ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL, 1296 propertyAnnotatedElement.element, propertyAnnotatedElement.inferredData, new HashMap <String , IdGenerator>(), 1297 new HashMap <String , Properties >(), entityBinder, isIdentifierMapper, mappings); 1298 } 1299 return comp; 1300 } 1301 1302 private static void bindId( 1303 String generatorType, String generatorName, 1304 PropertyInferredData inferredData, Ejb3Column column, PropertyHolder propertyHolder, 1305 Map <String , IdGenerator> localGenerators, HashMap <String , Properties > localGeneratorTables, boolean isComposite, Map <String , Column[]> columnOverride, boolean isPropertyAccess, 1306 EntityBinder entityBinder, Type typeAnn, boolean isEmbedded, ExtendedMappings mappings 1307 ) { 1308 1311 PersistentClass persistentClass = propertyHolder.getPersistentClass(); 1312 if ( ! ( persistentClass instanceof RootClass ) ) { 1313 throw new AnnotationException( 1314 "Unable to define/override @Id(s) on a subclass: " 1315 + propertyHolder.getEntityName() ); 1316 } 1317 RootClass rootClass = (RootClass) persistentClass; 1318 String persistentClassName = rootClass == null ? null : rootClass.getClassName(); 1319 SimpleValue id; 1320 if (isComposite) { 1321 id = fillComponent(propertyHolder, inferredData, isPropertyAccess, false, entityBinder, false, columnOverride, mappings); 1322 ( (Component) id).setKey(true); 1323 } 1324 else { 1325 column.forceNotNull(); SimpleValueBinder value = new SimpleValueBinder(); 1327 value.setPropertyName( inferredData.getPropertyName() ); 1328 value.setReturnedClassName( inferredData.getReturnedClassName() ); 1329 value.setColumns( new Ejb3Column[] { column } ); 1330 value.setPersistentClassName( persistentClassName ); 1331 value.setMappings( mappings ); 1332 value.setExplicitType(typeAnn); 1333 id = value.make(); 1334 } 1335 rootClass.setIdentifier(id); 1336 Table table = id.getTable(); 1337 table.setIdentifierValue(id); 1338 id.setIdentifierGeneratorStrategy(generatorType); 1340 Properties params = new Properties (); 1341 params.setProperty( 1343 PersistentIdentifierGenerator.TABLE, table.getName() 1344 ); 1345 params.setProperty( 1346 PersistentIdentifierGenerator.PK, 1347 ( (org.hibernate.mapping.Column) id.getColumnIterator().next() ).getName() 1348 ); 1349 if (! isDefault(generatorName) ) { 1350 IdGenerator gen = mappings.getGenerator(generatorName, localGenerators); 1352 if (gen == null) { 1353 throw new AnnotationException("Unknown Id.generator: " + generatorName); 1354 } 1355 final boolean overrideType = ! generatorType(GeneratorType.AUTO).equals( generatorType ); 1357 if ( overrideType ) { 1358 id.setIdentifierGeneratorStrategy( gen.getIdentifierGeneratorStrategy() ); 1359 } 1360 Iterator genParams = gen.getParams().entrySet().iterator(); 1362 while ( genParams.hasNext() ) { 1363 Map.Entry elt = (Map.Entry ) genParams.next(); 1364 params.setProperty( (String ) elt.getKey(), (String ) elt.getValue() ); 1365 } 1366 if ( MultipleHiLoPerTableGenerator.class.getName().equals(generatorType) ) { 1367 fillGeneratorWithGeneratorTableParams(params, localGeneratorTables, generatorName, mappings); 1369 } 1370 } 1371 if (generatorType == "assigned") id.setNullValue("undefined"); 1372 id.setIdentifierGeneratorProperties(params); 1373 if (isEmbedded) { 1374 rootClass.setEmbeddedIdentifier( inferredData.getReturnedClass() == null ); 1375 } 1376 else { 1377 PropertyBinder binder = new PropertyBinder(); 1378 binder.setName( inferredData.getPropertyName() ); 1379 binder.setValue(id); 1380 binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); 1381 Property prop = binder.make(); 1382 rootClass.setIdentifierProperty(prop); 1383 } 1384 } 1385 1386 1391 private static void checkIfMatchingGenerator(IdGenerator gen, String generatorType, String generatorName) { 1392 boolean matchingGenerator = gen.getIdentifierGeneratorStrategy().equals(generatorType); 1396 boolean defaultGenerator = generatorType(GeneratorType.AUTO).equals( generatorType ); 1397 1398 if ( ! ( matchingGenerator || defaultGenerator ) ) { 1399 throw new AnnotationException( 1401 "Incompatible generator between Id.generate and its named generator: " 1402 + generatorType + "!=" + generatorName); 1403 } 1404 } 1405 1406 private static void fillGeneratorWithGeneratorTableParams(Properties params, HashMap <String , Properties > localGeneratorTables, String generatorName, ExtendedMappings mappings) { 1407 final String generatorTableName = params.getProperty(GENERATOR_TABLE_NAME_PARAM); 1408 Properties props = mappings.getGeneratorTableProperties(generatorTableName, localGeneratorTables); 1409 if (props == null) { 1410 if ( MultipleHiLoPerTableGenerator.DEFAULT_TABLE.equals(generatorTableName) ) { 1411 return; 1413 } 1414 else { 1415 throw new AnnotationException("Unable to find a @GeneratedIdTable for table name in " + generatorName + ": " + generatorTableName ); 1416 } 1417 } 1418 else { 1419 Iterator properties = props.entrySet().iterator(); 1420 java.util.Map.Entry<String , String > property; 1421 while ( properties.hasNext() ) { 1422 property = (java.util.Map.Entry<String , String >) properties.next(); 1423 params.setProperty( property.getKey(), property.getValue() ); 1424 } 1425 } 1426 } 1427 1428 private static void bindManyToOne( 1429 String cascadeStrategy, Ejb3JoinColumn[] columns, boolean optional, FetchMode fetchMode, String propertyName, 1430 String returnedClassName, Class targetEntity, String propertyAccessorName, PropertyHolder propertyHolder, 1431 boolean unique, boolean isIdentifierMapper, ExtendedMappings mappings 1432 ) { 1433 org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne( columns[0].getTable() ); 1435 if ( isDefault(targetEntity) ) { 1436 value.setReferencedEntityName(returnedClassName); 1437 } 1438 else { 1439 value.setReferencedEntityName( targetEntity.getName() ); 1440 } 1441 value.setFetchMode(fetchMode); 1442 value.setLazy(fetchMode!=FetchMode.JOIN); 1443 if (!optional) { 1444 for(Ejb3JoinColumn column:columns) { 1445 column.setNullable(false); 1446 } 1447 } 1448 value.setTypeName(returnedClassName); 1449 value.setTypeUsingReflection(propertyHolder.getClassName() , propertyName); 1450 String propertyRef = value.getReferencedPropertyName(); 1451 1452 mappings.addSecondPass( new FkSecondPass(value, columns, unique, mappings) ); 1454 1455 Ejb3Column.checkPropertyConsistency(columns, propertyHolder.getEntityName() + propertyName); 1456 PropertyBinder binder = new PropertyBinder(); 1457 binder.setName(propertyName); 1458 binder.setValue(value); 1459 binder.setCascade(cascadeStrategy); 1460 if (isIdentifierMapper) { 1461 binder.setInsertable(false); 1462 binder.setInsertable(false); 1463 } 1464 else { 1465 binder.setInsertable( columns[0].isInsertable() ); 1466 binder.setUpdatable( columns[0].isUpdatable() ); 1467 } 1468 binder.setPropertyAccessorName( propertyAccessorName ); 1469 binder.setCascade(cascadeStrategy); 1470 Property prop = binder.make(); 1471 columns[0].addPropertyToMappingContainer(prop); 1473 } 1474 1475 public static void bindFkSecondPass( 1476 org.hibernate.mapping.ManyToOne manyToOne, Ejb3JoinColumn[] columns, Map persistentClasses, boolean unique, 1477 ExtendedMappings mappings 1478 ) { 1479 PersistentClass ref = (PersistentClass) persistentClasses.get( manyToOne.getReferencedEntityName() ); 1480 if (ref == null) throw new AnnotationException("Unable to find entity " + manyToOne.getReferencedEntityName() ); 1481 BinderHelper.createSyntheticPropertyReference( columns, ref, manyToOne, mappings ); 1482 TableBinder.bindFk(ref, null, columns, manyToOne, unique ); 1483 } 1484 1485 private static void bindOneToOne( 1486 String cascadeStrategy, 1487 Ejb3JoinColumn[] columns, 1488 boolean optional, 1489 FetchMode fetchMode, 1490 String propertyName, 1491 String returnedClassName, 1492 Class targetEntity, 1493 String propertyAccessorName, 1494 PropertyHolder propertyHolder, 1495 String mappedBy, 1496 boolean trueOneToOne, 1497 boolean isIdentifierMapper, ExtendedMappings mappings 1498 ) { 1499 log.debug("Fetching " + propertyName + " with " + fetchMode); 1501 boolean mapToPK = true; 1502 if ( ! trueOneToOne ) { 1503 Iterator idColumns = propertyHolder.getIdentifier().getColumnIterator(); 1505 List <String > idColumnNames = new ArrayList <String >(); 1506 org.hibernate.mapping.Column currentColumn; 1507 while( idColumns.hasNext() ) { 1508 currentColumn = (org.hibernate.mapping.Column) idColumns.next(); 1509 idColumnNames.add( currentColumn.getName() ); 1510 } 1511 for (Ejb3JoinColumn col : columns) { 1512 if ( ! idColumnNames.contains( col.getMappingColumn().getName() ) ) { 1513 mapToPK = false; 1514 break; 1515 } 1516 } 1517 } 1518 if ( trueOneToOne || mapToPK || ! isDefault(mappedBy) ) { 1519 org.hibernate.mapping.OneToOne value = new org.hibernate.mapping.OneToOne( propertyHolder.getTable(), propertyHolder.getPersistentClass() ); 1522 value.setPropertyName( propertyName ); 1523 if ( isDefault(targetEntity) ) { 1524 value.setReferencedEntityName(returnedClassName); 1525 } 1526 else { 1527 value.setReferencedEntityName( targetEntity.getName() ); 1528 } 1529 value.setFetchMode(fetchMode); 1530 value.setLazy(fetchMode!=FetchMode.JOIN); 1531 1532 if (!optional) value.setConstrained(true); 1533 value.setForeignKeyType( 1535 value.isConstrained() ? 1536 ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : 1537 ForeignKeyDirection.FOREIGN_KEY_TO_PARENT 1538 ); 1539 if ( ! isDefault(mappedBy) ) value.setReferencedPropertyName(mappedBy); 1540 1541 String propertyRef = value.getReferencedPropertyName(); 1542 if (propertyRef!=null) mappings.addUniquePropertyReference( 1543 value.getReferencedEntityName(), 1544 propertyRef 1545 ); 1546 PropertyBinder binder = new PropertyBinder(); 1548 binder.setName(propertyName); 1549 binder.setValue(value); 1550 binder.setCascade(cascadeStrategy); 1551 binder.setPropertyAccessorName(propertyAccessorName); 1552 Property prop = binder.make(); 1553 prop.setCascade(cascadeStrategy); 1554 propertyHolder.addProperty(prop); 1556 } 1557 else { 1558 bindManyToOne(cascadeStrategy, columns, optional, fetchMode, propertyName, returnedClassName, targetEntity, 1560 propertyAccessorName, propertyHolder, true, isIdentifierMapper, mappings); 1561 } 1562 } 1563 1564 private static String generatorType(GeneratorType generatorEnum) { 1565 switch ( generatorEnum ) { 1566 case NONE : return "assigned"; 1567 case IDENTITY:return "identity"; 1568 case AUTO:return "native"; 1569 case TABLE:return MultipleHiLoPerTableGenerator.class.getName(); 1570 case SEQUENCE:return "sequence"; 1571 } 1572 throw new AssertionFailure("Unknown GeneratorType: " + generatorEnum); 1573 } 1574 1575 private static EnumSet <CascadeType> convertToHibernateCascadeType(javax.persistence.CascadeType[] ejbCascades) { 1576 EnumSet <CascadeType> hibernateCascadeSet = EnumSet.noneOf(CascadeType.class); 1577 if (ejbCascades != null && ejbCascades.length > 0) { 1578 for(javax.persistence.CascadeType cascade : ejbCascades) { 1579 switch (cascade) { 1580 case ALL: 1581 hibernateCascadeSet.add(CascadeType.ALL); 1582 break; 1583 case PERSIST: 1584 hibernateCascadeSet.add(CascadeType.PERSIST); 1585 break; 1586 case MERGE: 1587 hibernateCascadeSet.add(CascadeType.MERGE); 1588 break; 1589 case REMOVE: 1590 hibernateCascadeSet.add(CascadeType.REMOVE); 1591 break; 1592 case REFRESH: 1593 hibernateCascadeSet.add(CascadeType.REFRESH); 1594 break; 1595 } 1596 } 1597 } 1598 1599 return hibernateCascadeSet; 1600 } 1601 1602 private static String getCascadeStrategy(javax.persistence.CascadeType[] ejbCascades, Cascade hibernateCascadeAnnotation) { 1603 EnumSet <CascadeType> hibernateCascadeSet = convertToHibernateCascadeType(ejbCascades); 1604 CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null ? null : hibernateCascadeAnnotation.value(); 1605 1606 if (hibernateCascades != null && hibernateCascades.length > 0) { 1607 for (CascadeType cascadeType : hibernateCascades) { 1608 hibernateCascadeSet.add(cascadeType); 1609 } 1610 } 1611 1612 StringBuffer cascade = new StringBuffer (); 1613 Iterator <CascadeType> cascadeType = hibernateCascadeSet.iterator(); 1614 while ( cascadeType.hasNext() ) { 1615 switch( cascadeType.next() ) { 1616 case ALL: 1617 cascade.append(",").append("all"); 1618 break; 1619 case SAVE_UPDATE: 1620 cascade.append(",").append("save-update"); 1621 break; 1622 case PERSIST: 1623 cascade.append(",").append("persist"); 1624 break; 1625 case MERGE: 1626 cascade.append(",").append("merge"); 1627 break; 1628 case LOCK: 1629 cascade.append(",").append("lock"); 1630 break; 1631 case REFRESH: 1632 cascade.append(",").append("refresh"); 1633 break; 1634 case REPLICATE: 1635 cascade.append(",").append("replicate"); 1636 break; 1637 case EVICT: 1638 cascade.append(",").append("evict"); 1639 break; 1640 case DELETE: 1641 cascade.append(",").append("delete"); 1642 break; 1643 case DELETE_ORPHAN: 1644 cascade.append(",").append("delete-orphan"); 1645 break; 1646 case REMOVE: 1647 cascade.append(",").append("delete"); 1648 break; 1649 } 1650 } 1651 return cascade.length() > 0 ? cascade.substring(1) : "none"; 1652 } 1653 1654 private static FetchMode getFetchMode(FetchType fetch) { 1655 if (fetch == FetchType.EAGER) { 1656 return FetchMode.JOIN; 1657 } 1658 else { 1659 return FetchMode.SELECT; 1660 } 1661 } 1662 1663 private static HashMap <String ,IdGenerator> buildLocalGenerators(AnnotatedElement annElt) { 1664 HashMap <String ,IdGenerator> generators = new HashMap <String , IdGenerator>(); 1665 TableGenerator tabGen = annElt.getAnnotation( TableGenerator.class ); 1666 SequenceGenerator seqGen = annElt.getAnnotation( SequenceGenerator.class ); 1667 GenericGenerator genGen = annElt.getAnnotation( GenericGenerator.class ); 1668 if (tabGen != null) { 1669 IdGenerator idGen = buildIdGenerator(tabGen); 1670 generators.put(idGen.getName(), idGen); 1671 } 1672 if (seqGen != null) { 1673 IdGenerator idGen = buildIdGenerator(seqGen); 1674 generators.put(idGen.getName(), idGen); 1675 } 1676 if (genGen != null) { 1677 IdGenerator idGen = buildIdGenerator( genGen); 1678 generators.put( idGen.getName(), idGen ); 1679 } 1680 return generators; 1681 } 1682 1683 public static boolean isDefault(String annotationString) { 1684 return ANNOTATION_STRING_DEFAULT.equals(annotationString); 1685 } 1686 1687 public static boolean isDefault(Class clazz) { 1688 return void.class.equals(clazz); 1689 } 1690 1691 public static Map <Class , InheritanceState> buildInheritanceStates(List <Class > orderedClasses) { 1692 Map <Class , InheritanceState> inheritanceStatePerClass = new HashMap <Class , InheritanceState>( orderedClasses.size() ); 1693 for (Class clazz : orderedClasses) { 1694 Class superClazz = clazz.getSuperclass(); 1695 InheritanceState state = new InheritanceState(); 1696 state.setInheritanceType(clazz); 1697 if ( orderedClasses.contains(superClazz) ) { 1698 InheritanceState superState = inheritanceStatePerClass.get(superClazz); 1700 superState.hasSons = true; 1701 if (superState.isEmbeddableSuperclass == true) { 1702 state.hasParents = false; 1703 state.hasEmbeddedSuperclass = true; 1704 } 1705 else { 1706 state.hasParents = true; 1707 state.hasEmbeddedSuperclass = false; 1708 } 1709 final boolean nonDefault = ! InheritanceType.SINGLE_TABLE.equals( state.type ); 1710 if (superState.type != null) { 1711 final boolean mixingStrategy = ! state.type.equals( superState.type ); 1712 if ( nonDefault && mixingStrategy ) { 1713 log.warn("Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: " + clazz.getName() ); 1714 } 1715 state.type = superState.type; 1716 } 1717 } 1718 inheritanceStatePerClass.put(clazz, state); 1719 } 1720 return inheritanceStatePerClass; 1721 } 1722 1723 private static class PropertyAnnotatedElement { 1724 public PropertyAnnotatedElement(AnnotatedElement elt) { 1725 element = elt; 1726 inferredData = new PropertyInferredData(element); 1727 } 1728 public AnnotatedElement element; 1729 public PropertyInferredData inferredData; 1730 } 1731} 1732 | Popular Tags |