1 package org.hibernate.cfg.annotations; 3 4 import java.lang.reflect.Modifier ; 5 import java.util.ArrayList ; 6 import java.util.HashMap ; 7 import java.util.Iterator ; 8 import java.util.List ; 9 import java.util.Map ; 10 import javax.persistence.AccessType; 11 import javax.persistence.Entity; 12 import javax.persistence.JoinColumn; 13 import javax.persistence.JoinColumns; 14 import javax.persistence.SecondaryTable; 15 import javax.persistence.SecondaryTables; 16 import javax.persistence.UniqueConstraint; 17 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 import org.hibernate.AnnotationException; 21 import org.hibernate.AssertionFailure; 22 import org.hibernate.MappingException; 23 import org.hibernate.annotations.BatchSize; 24 import org.hibernate.annotations.Cache; 25 import org.hibernate.annotations.CacheConcurrencyStrategy; 26 import org.hibernate.annotations.OptimisticLockType; 27 import org.hibernate.annotations.PolymorphismType; 28 import org.hibernate.annotations.Proxy; 29 import org.hibernate.annotations.Tables; 30 import org.hibernate.annotations.Where; 31 import org.hibernate.cache.CacheFactory; 32 import org.hibernate.cfg.AnnotationBinder; 33 import org.hibernate.cfg.Ejb3JoinColumn; 34 import org.hibernate.cfg.ExtendedMappings; 35 import org.hibernate.cfg.InheritanceState; 36 import org.hibernate.cfg.PropertyHolder; 37 import org.hibernate.engine.Versioning; 38 import org.hibernate.mapping.DependantValue; 39 import org.hibernate.mapping.Join; 40 import org.hibernate.mapping.PersistentClass; 41 import org.hibernate.mapping.RootClass; 42 import org.hibernate.mapping.SimpleValue; 43 import org.hibernate.mapping.Table; 44 import org.hibernate.mapping.TableOwner; 45 import org.hibernate.util.ReflectHelper; 46 import org.hibernate.util.StringHelper; 47 48 53 public class EntityBinder { 54 private String name; 55 private Class annotatedClass; 56 private PersistentClass persistentClass; 57 private ExtendedMappings mappings; 58 private static Log log = LogFactory.getLog(EntityBinder.class); 59 private String discriminatorValue = ""; 60 private boolean propertyAccess = false; 61 private boolean dynamicInsert; 62 private boolean dynamicUpdate; 63 private boolean mutable; 64 private OptimisticLockType optimisticLockType; 65 private String persister; 66 private PolymorphismType polymorphismType; 67 private boolean selectBeforeUpdate; 68 private int batchSize; 69 private boolean lazy; 70 private String proxyClassName; 71 private String where; 72 private java.util.Map <String , Join> secondaryTables = new HashMap <String , Join>(); 73 private java.util.Map <String , Object > secondaryTableJoins = new HashMap <String , Object >(); 74 private String cacheConcurrentStrategy; 75 private String cacheRegion; 76 private java.util.Map <String ,String > filters = new HashMap <String , String >(); 77 private InheritanceState inheritanceState; 78 private boolean ignoreIdAnnotations; 79 80 public boolean isPropertyAccess() { 81 return propertyAccess; 82 } 83 84 public EntityBinder(Entity ejb3Ann, org.hibernate.annotations.Entity hibAnn, 85 Class annotatedClass, PersistentClass persistentClass, 86 ExtendedMappings mappings) { 87 this.mappings = mappings; 88 this.persistentClass = persistentClass; 89 this.annotatedClass = annotatedClass; 90 bindEjb3Annotation(ejb3Ann); 91 bindHibernateAnnotation(hibAnn); 92 } 93 94 private void bindHibernateAnnotation(org.hibernate.annotations.Entity hibAnn) { 95 if (hibAnn != null) { 96 dynamicInsert = hibAnn.dynamicInsert(); 97 dynamicUpdate = hibAnn.dynamicUpdate(); 98 mutable = hibAnn.mutable(); 99 optimisticLockType = hibAnn.optimisticLock(); 100 persister = hibAnn.persister(); 101 selectBeforeUpdate = hibAnn.selectBeforeUpdate(); 102 polymorphismType = hibAnn.polymorphism(); 103 } 104 else { 105 dynamicInsert = false; 107 dynamicUpdate = false; 108 mutable = true; 109 optimisticLockType = OptimisticLockType.VERSION; 110 persister = ""; 111 polymorphismType = PolymorphismType.IMPLICIT; 112 selectBeforeUpdate = false; 113 } 114 } 115 116 private void bindEjb3Annotation(Entity ejb3Ann) { 117 if (ejb3Ann == null) throw new AssertionFailure("@Entity should always be not null"); 118 if ( AnnotationBinder.isDefault( ejb3Ann.name() ) ) { 119 name = StringHelper.unqualify( annotatedClass.getName() ); 120 } 121 else { 122 name = ejb3Ann.name(); 123 } 124 propertyAccess = ejb3Ann.access() == AccessType.PROPERTY; 125 } 126 127 public void setDiscriminatorValue(String discriminatorValue) { 128 this.discriminatorValue = discriminatorValue; 129 } 130 131 public void bindEntity() { 132 persistentClass.setAbstract( Modifier.isAbstract( annotatedClass.getModifiers() ) ); 133 persistentClass.setClassName( annotatedClass.getName() ); 134 persistentClass.setEntityName( annotatedClass.getName() ); 136 if ( StringHelper.isEmpty( discriminatorValue ) ) { 137 persistentClass.setDiscriminatorValue( persistentClass.getEntityName() ); 138 } 139 else { 140 persistentClass.setDiscriminatorValue(discriminatorValue); 141 } 142 143 persistentClass.setLazy(lazy); 144 if (! StringHelper.isEmpty(proxyClassName) ) { 145 persistentClass.setProxyInterfaceName(proxyClassName); 146 } 147 persistentClass.setDynamicInsert(dynamicInsert); 148 persistentClass.setDynamicUpdate(dynamicUpdate); 149 if (persistentClass instanceof RootClass) { 150 RootClass rootClass = (RootClass) persistentClass; 151 rootClass.setMutable(mutable); 152 rootClass.setExplicitPolymorphism( isExplicitPolymorphism(polymorphismType) ); 153 if ( StringHelper.isNotEmpty(where) ) rootClass.setWhere(where); 154 if ( cacheConcurrentStrategy != null) { 155 rootClass.setCacheConcurrencyStrategy(cacheConcurrentStrategy); 156 rootClass.setCacheRegionName(cacheRegion); 157 } 158 } 159 persistentClass.setOptimisticLockMode( getVersioning(optimisticLockType) ); 160 persistentClass.setSelectBeforeUpdate(selectBeforeUpdate); 161 if (! AnnotationBinder.isDefault(persister) ) { 162 try { 163 persistentClass.setEntityPersisterClass( ReflectHelper.classForName(persister) ); 164 } 165 catch ( ClassNotFoundException cnfe ) { 166 throw new AnnotationException("Could not find persister class: " + persister); 167 } 168 } 169 persistentClass.setBatchSize(batchSize); 170 171 if (! inheritanceState.hasParents) { 172 Iterator <Map.Entry <String ,String >> iter = filters.entrySet().iterator(); 173 while ( iter.hasNext() ) { 174 Map.Entry <String ,String > filter = iter.next(); 175 persistentClass.addFilter( filter.getKey(), filter.getValue() ); 176 } 177 } 178 else { 179 if ( filters.size() > 0) 180 log.warn("@Filter not allowed on subclasses (ignored): " + persistentClass.getEntityName() ); 181 } 182 log.debug("Import with entity name=" + name); 183 try { 184 mappings.addImport(persistentClass.getEntityName(), name); 185 } 186 catch (MappingException me) { 187 throw new AnnotationException("Use of the same entity name twice: " + name); 188 } 189 } 190 191 int getVersioning(OptimisticLockType type) { 192 switch(type) { 193 case VERSION: 194 return Versioning.OPTIMISTIC_LOCK_VERSION; 195 case NONE: 196 return Versioning.OPTIMISTIC_LOCK_NONE; 197 case DIRTY: 198 return Versioning.OPTIMISTIC_LOCK_DIRTY; 199 case ALL: 200 return Versioning.OPTIMISTIC_LOCK_ALL; 201 default: 202 throw new AssertionFailure("optimistic locking not supported: " + type); 203 } 204 } 205 206 private boolean isExplicitPolymorphism(PolymorphismType type) { 207 switch(type) { 208 case IMPLICIT: 209 return false; 210 case EXPLICIT: 211 return true; 212 default: 213 throw new AssertionFailure("Unknown polymorphism type: " + type); 214 } 215 } 216 217 public void setBatchSize(BatchSize sizeAnn) { 218 if (sizeAnn != null) { 219 batchSize = sizeAnn.size(); 220 } 221 else { 222 batchSize = -1; 223 } 224 } 225 226 public void setProxy(Proxy proxy) { 227 if (proxy != null) { 228 lazy = proxy.lazy(); 229 if (!lazy) { 230 proxyClassName = null; 231 } 232 else { 233 if ( AnnotationBinder.isDefault( proxy.proxyClassName() ) ) { 234 proxyClassName = annotatedClass.getName(); 235 } 236 else { 237 proxyClassName = proxy.proxyClassName(); 238 } 239 } 240 } 241 else { 242 lazy = true; proxyClassName = annotatedClass.getName(); 244 } 245 } 246 247 public void setWhere(Where whereAnn) { 248 if (whereAnn != null) { 249 where = whereAnn.clause(); 250 } 251 } 252 253 private String getClassTableName(String tableName) { 254 if ( StringHelper.isEmpty(tableName) ) { 255 return mappings.getNamingStrategy().classToTableName( persistentClass.getEntityName() ); 256 } 257 else { 258 return mappings.getNamingStrategy().tableName(tableName); 259 } 260 } 261 262 public void bindTable( 263 String schema, String catalog, 264 String tableName, List uniqueConstraints, 265 String constraints, Table denormalizedSuperclassTable 266 ) { 267 Table table = TableBinder.fillTable( 268 schema, catalog, 269 getClassTableName(tableName), 270 persistentClass.isAbstract(), uniqueConstraints, constraints, 271 denormalizedSuperclassTable, mappings 272 ); 273 274 if (persistentClass instanceof TableOwner) { 275 ( (TableOwner) persistentClass).setTable(table); 276 } 277 else { 278 throw new AssertionFailure("binding a table for a subclass"); 279 } 280 } 281 282 public void finalSecondaryTableBinding(PropertyHolder propertyHolder) { 283 287 Iterator joins = secondaryTables.values().iterator(); 288 Iterator joinColumns = secondaryTableJoins.values().iterator(); 289 290 while ( joins.hasNext() ) { 291 Object uncastedColumn = joinColumns.next(); 292 293 Ejb3JoinColumn[] ejb3JoinColumns; 294 JoinColumn[] columns = null; 295 if ( uncastedColumn instanceof JoinColumn[] ) { 296 columns = (JoinColumn[]) uncastedColumn; 297 } 298 if (columns == null) { 299 ejb3JoinColumns = new Ejb3JoinColumn[1]; 300 ejb3JoinColumns[0] = Ejb3JoinColumn.buildJoinColumn( 301 (JoinColumn) uncastedColumn, 302 persistentClass.getIdentifier(), 303 secondaryTables, 304 propertyHolder, mappings 305 ); 306 } 307 else { 308 int nbrOfJoinColumns = columns.length; 309 if (nbrOfJoinColumns == 0) { 310 ejb3JoinColumns = new Ejb3JoinColumn[1]; 311 ejb3JoinColumns[0] = Ejb3JoinColumn.buildJoinColumn( 312 (JoinColumn) null, 313 persistentClass.getIdentifier(), 314 secondaryTables, 315 propertyHolder, mappings 316 ); 317 } 318 else { 319 ejb3JoinColumns = new Ejb3JoinColumn[nbrOfJoinColumns]; 320 for (int colIndex = 0 ; colIndex < nbrOfJoinColumns ; colIndex++) { 321 ejb3JoinColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn( 322 columns[colIndex], 323 persistentClass.getIdentifier(), 324 secondaryTables, 325 propertyHolder, mappings 326 ); 327 } 328 } 329 } 330 331 for (Ejb3JoinColumn joinColumn : ejb3JoinColumns) { 332 joinColumn.forceNotNull(); 333 } 334 Join join = (Join) joins.next(); 335 bindJoinToPersistentClass(join, ejb3JoinColumns, persistentClass, mappings ); 336 } 337 mappings.addJoins(persistentClass, secondaryTables); 338 } 339 340 public static void bindJoinToPersistentClass( 341 Join join, Ejb3JoinColumn[] ejb3JoinColumns, PersistentClass persistentClass, ExtendedMappings mappings 342 ) { 343 SimpleValue key = new DependantValue( join.getTable(), persistentClass.getIdentifier() ); 344 join.setKey(key); 345 join.setSequentialSelect(false); 346 join.setInverse(false); 347 join.setOptional(true); key.setCascadeDeleteEnabled(false); 349 TableBinder.bindFk(persistentClass, null, ejb3JoinColumns, key, false ); 350 join.createPrimaryKey(); 351 join.createForeignKey(); 352 persistentClass.addJoin(join); 353 } 354 355 public void firstLevelSecondaryTablesBinding(SecondaryTable secTable, SecondaryTables secTables, JoinColumn joinCol, JoinColumns joinCols) { 356 if (secTables != null) { 357 for (SecondaryTable tab : secTables.value() ) { 359 bindFirstLevelSecondaryTable(tab, null, null); 360 } 361 } 362 else { 363 if (secTable != null) bindFirstLevelSecondaryTable(secTable, joinCol, joinCols); 364 } 365 } 366 367 private void bindFirstLevelSecondaryTable(SecondaryTable tabAnn, JoinColumn joinColAnn, JoinColumns joinColsAnn) { 368 List uniqueConstraints = new ArrayList (); 369 if (tabAnn.uniqueConstraints().length != 0) { 370 for( UniqueConstraint uc : tabAnn.uniqueConstraints() ) { 371 uniqueConstraints.add( uc.columnNames() ); 372 } 373 } 374 addSecondaryTable( 375 tabAnn.schema(), 376 tabAnn.catalog(), 377 tabAnn.name(), 378 uniqueConstraints, 379 joinColAnn, 380 joinColsAnn == null ? tabAnn.join() : joinColsAnn.value() 381 ); 382 } 383 384 413 public void addSecondaryTable(String schema, String catalog, String table, List uniqueConstraints, JoinColumn joinColAnn, JoinColumn[] joinColArray) { 414 Join join = buildJoin(schema, catalog, table, uniqueConstraints, persistentClass, mappings); 415 if (joinColAnn != null) { 418 secondaryTableJoins.put( table, joinColAnn ); 419 } 420 else { 421 secondaryTableJoins.put( table, joinColArray ); 422 } 423 log.info("Mapping class join: " + persistentClass.getEntityName() + " -> " + join.getTable().getName() ); 424 secondaryTables.put( table, join ); 425 } 426 427 public static Join buildJoin(String schema, String catalog, String table, List uniqueConstraints, PersistentClass persistentClass, ExtendedMappings mappings) { 428 Join join = new Join(); 429 join.setPersistentClass(persistentClass); 430 Table tableMapping = TableBinder.fillTable( 431 schema, catalog, table, 432 false, uniqueConstraints, null, null, mappings 433 ); 434 join.setTable(tableMapping); 436 return join; 437 } 438 439 public java.util.Map <String , Join> getSecondaryTables() { 440 return secondaryTables; 441 } 442 443 public void setCache(Cache cacheAnn) { 444 if (cacheAnn != null) { 445 cacheRegion = AnnotationBinder.isDefault( cacheAnn.region() ) ? null : cacheAnn.region(); 446 cacheConcurrentStrategy = getCacheConcurrencyStrategy( cacheAnn.usage() ); 447 } 448 else { 449 cacheConcurrentStrategy = null; 450 cacheRegion = null; 451 } 452 } 453 454 public static String getCacheConcurrencyStrategy(CacheConcurrencyStrategy strategy) { 455 switch ( strategy ) { 456 case NONE: 457 return null; 458 case READ_ONLY: 459 return CacheFactory.READ_ONLY; 460 case READ_WRITE: 461 return CacheFactory.READ_WRITE; 462 case NONSTRICT_READ_WRITE: 463 return CacheFactory.NONSTRICT_READ_WRITE; 464 case TRANSACTIONAL: 465 return CacheFactory.TRANSACTIONAL; 466 default: 467 throw new AssertionFailure( "CacheConcurrencyStrategy unknown: " + strategy ); 468 } 469 } 470 471 public void addFilter(String name, String condition) { 472 filters.put(name, condition); 473 } 474 475 public void setInheritanceState(InheritanceState inheritanceState) { 476 this.inheritanceState = inheritanceState; 477 } 478 479 public InheritanceState getInheritanceState() { 480 return inheritanceState; 481 } 482 483 public boolean isIgnoreIdAnnotations() { 484 return ignoreIdAnnotations; 485 } 486 487 public void setIgnoreIdAnnotations(boolean ignoreIdAnnotations) { 488 this.ignoreIdAnnotations = ignoreIdAnnotations; 489 } 490 491 public void addIndexes(org.hibernate.annotations.Table table) { 492 if (table == null) return; 493 String tableName = table.name(); 494 Iterator tables = persistentClass.getTableClosureIterator(); 495 Table hibTable = null; 496 while ( tables.hasNext() ) { 497 hibTable = (Table) tables.next(); 498 if ( hibTable.getName().equals( tableName) ) { 499 break; 501 } 502 } 503 if (hibTable == null) { 504 throw new AnnotationException("@org.hibernate.annotations.Table references an unknown table: " + tableName); 505 } 506 TableBinder.addIndexes( hibTable, table.indexes() ); 507 } 508 509 public void addIndexes(Tables tables) { 510 if (tables == null) return; 511 for (org.hibernate.annotations.Table table : tables.values() ) { 512 addIndexes( table ); 513 } 514 } 515 } 516 | Popular Tags |