hibernate3.6.10 注解配置添加表字段注释


如果使用的是xml方式配置,则使用comment即可:

<property name="name"  >
      <column name="name_col">
      <comment>我是注释</comment>
      </column>
    </property>

下面的方法是修改hibernate3.6.10源码、添加注解配置的处理信息:

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package org.hibernate.cfg;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. @Target({ElementType.TYPE,ElementType.FIELD})    
  9. @Retention(RetentionPolicy.RUNTIME)    
  10. public @interface Comment {    
  11.     String value() default "";    
  12. }    
[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package org.hibernate.cfg;  
  2.   
  3.     
  4. import org.hibernate.annotations.common.reflection.XClass;    
  5. import org.hibernate.annotations.common.reflection.XProperty;    
  6. import org.hibernate.cfg.Ejb3Column;    
  7. import org.hibernate.mapping.PersistentClass;    
  8.     
  9.   
  10. public class CommentBinder {    
  11.       
  12.     public static void bindTableComment(XClass clazzToProcess, PersistentClass persistentClass) {    
  13.         //System.out.println("处理表名注释!");  
  14.         if (clazzToProcess.isAnnotationPresent(Comment.class)) {    
  15.             String tableComment = clazzToProcess.getAnnotation(Comment.class).value();    
  16.             persistentClass.getTable().setComment(tableComment);    
  17.     
  18.         }    
  19.     }    
  20.     
  21.     public static void bindColumnComment(XProperty property, Ejb3Column[] columns) {    
  22.         //System.out.println("处理多字段注释"+property+columns);  
  23.         if (null != columns)    
  24.             if (property.isAnnotationPresent(Comment.class)) {    
  25.                 String comment = property.getAnnotation(Comment.class).value();    
  26.                 for (Ejb3Column column : columns) {    
  27.                     column.getMappingColumn().setComment(comment);    
  28.                 }    
  29.     
  30.             }    
  31.     }    
  32.     
  33.     public static void bindColumnComment(XProperty property, Ejb3Column column) {    
  34.         //System.out.println("处理字段注释");  
  35.         if (null != column)    
  36.             if (property.isAnnotationPresent(Comment.class)) {    
  37.                 String comment = property.getAnnotation(Comment.class).value();    
  38.     
  39.                 column.getMappingColumn().setComment(comment);    
  40.     
  41.             }    
  42.     }    
  43. }    

下面这个类路径不能变、覆盖hibernate对应的源码。

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
    1. /* 
    2.  * Hibernate, Relational Persistence for Idiomatic Java 
    3.  * 
    4.  * Copyright (c) 2010, Red Hat Inc. or third-party contributors as 
    5.  * indicated by the @author tags or express copyright attribution 
    6.  * statements applied by the authors.  All third-party contributions are 
    7.  * distributed under license by Red Hat Inc. 
    8.  * 
    9.  * This copyrighted material is made available to anyone wishing to use, modify, 
    10.  * copy, or redistribute it subject to the terms and conditions of the GNU 
    11.  * Lesser General Public License, as published by the Free Software Foundation. 
    12.  * 
    13.  * This program is distributed in the hope that it will be useful, 
    14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
    15.  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License 
    16.  * for more details. 
    17.  * 
    18.  * You should have received a copy of the GNU Lesser General Public License 
    19.  * along with this distribution; if not, write to: 
    20.  * Free Software Foundation, Inc. 
    21.  * 51 Franklin Street, Fifth Floor 
    22.  * Boston, MA  02110-1301  USA 
    23.  */  
    24. package org.hibernate.cfg;  
    25.   
    26. import java.lang.annotation.Annotation;  
    27. import java.util.ArrayList;  
    28. import java.util.Arrays;  
    29. import java.util.Collection;  
    30. import java.util.EnumSet;  
    31. import java.util.HashMap;  
    32. import java.util.HashSet;  
    33. import java.util.Iterator;  
    34. import java.util.List;  
    35. import java.util.Map;  
    36. import java.util.Properties;  
    37. import java.util.Set;  
    38. import javax.persistence.Basic;  
    39. import javax.persistence.Cacheable;  
    40. import javax.persistence.CollectionTable;  
    41. import javax.persistence.Column;  
    42. import javax.persistence.DiscriminatorType;  
    43. import javax.persistence.DiscriminatorValue;  
    44. import javax.persistence.ElementCollection;  
    45. import javax.persistence.Embeddable;  
    46. import javax.persistence.Embedded;  
    47. import javax.persistence.EmbeddedId;  
    48. import javax.persistence.Entity;  
    49. import javax.persistence.FetchType;  
    50. import javax.persistence.GeneratedValue;  
    51. import javax.persistence.GenerationType;  
    52. import javax.persistence.Id;  
    53. import javax.persistence.IdClass;  
    54. import javax.persistence.InheritanceType;  
    55. import javax.persistence.JoinColumn;  
    56. import javax.persistence.JoinTable;  
    57. import javax.persistence.ManyToMany;  
    58. import javax.persistence.ManyToOne;  
    59. import javax.persistence.MapKey;  
    60. import javax.persistence.MapKeyColumn;  
    61. import javax.persistence.MapKeyJoinColumn;  
    62. import javax.persistence.MapKeyJoinColumns;  
    63. import javax.persistence.MappedSuperclass;  
    64. import javax.persistence.MapsId;  
    65. import javax.persistence.NamedNativeQueries;  
    66. import javax.persistence.NamedNativeQuery;  
    67. import javax.persistence.NamedQueries;  
    68. import javax.persistence.NamedQuery;  
    69. import javax.persistence.OneToMany;  
    70. import javax.persistence.OneToOne;  
    71. import javax.persistence.OrderColumn;  
    72. import javax.persistence.PrimaryKeyJoinColumn;  
    73. import javax.persistence.PrimaryKeyJoinColumns;  
    74. import javax.persistence.SequenceGenerator;  
    75. import javax.persistence.SharedCacheMode;  
    76. import javax.persistence.SqlResultSetMapping;  
    77. import javax.persistence.SqlResultSetMappings;  
    78. import javax.persistence.Table;  
    79. import javax.persistence.TableGenerator;  
    80. import javax.persistence.UniqueConstraint;  
    81. import javax.persistence.Version;  
    82.   
    83. import org.slf4j.Logger;  
    84. import org.slf4j.LoggerFactory;  
    85.   
    86. import org.hibernate.AnnotationException;  
    87. import org.hibernate.AssertionFailure;  
    88. import org.hibernate.EntityMode;  
    89. import org.hibernate.FetchMode;  
    90. import org.hibernate.MappingException;  
    91. import org.hibernate.annotations.BatchSize;  
    92. import org.hibernate.annotations.Cache;  
    93. import org.hibernate.annotations.CacheConcurrencyStrategy;  
    94. import org.hibernate.annotations.Cascade;  
    95. import org.hibernate.annotations.CascadeType;  
    96. import org.hibernate.annotations.Check;  
    97. import org.hibernate.annotations.CollectionId;  
    98. import org.hibernate.annotations.CollectionOfElements;  
    99. import org.hibernate.annotations.Columns;  
    100. import org.hibernate.annotations.DiscriminatorOptions;  
    101. import org.hibernate.annotations.Fetch;  
    102. import org.hibernate.annotations.FetchProfile;  
    103. import org.hibernate.annotations.FetchProfiles;  
    104. import org.hibernate.annotations.Filter;  
    105. import org.hibernate.annotations.FilterDef;  
    106. import org.hibernate.annotations.FilterDefs;  
    107. import org.hibernate.annotations.Filters;  
    108. import org.hibernate.annotations.ForceDiscriminator;  
    109. import org.hibernate.annotations.ForeignKey;  
    110. import org.hibernate.annotations.Formula;  
    111. import org.hibernate.annotations.GenericGenerator;  
    112. import org.hibernate.annotations.GenericGenerators;  
    113. import org.hibernate.annotations.Index;  
    114. import org.hibernate.annotations.LazyToOne;  
    115. import org.hibernate.annotations.LazyToOneOption;  
    116. import org.hibernate.annotations.ManyToAny;  
    117. import org.hibernate.annotations.MapKeyType;  
    118. import org.hibernate.annotations.NaturalId;  
    119. import org.hibernate.annotations.NotFound;  
    120. import org.hibernate.annotations.NotFoundAction;  
    121. import org.hibernate.annotations.OnDelete;  
    122. import org.hibernate.annotations.OnDeleteAction;  
    123. import org.hibernate.annotations.OrderBy;  
    124. import org.hibernate.annotations.ParamDef;  
    125. import org.hibernate.annotations.Parameter;  
    126. import org.hibernate.annotations.Parent;  
    127. import org.hibernate.annotations.Proxy;  
    128. import org.hibernate.annotations.Sort;  
    129. import org.hibernate.annotations.Source;  
    130. import org.hibernate.annotations.Tuplizer;  
    131. import org.hibernate.annotations.Tuplizers;  
    132. import org.hibernate.annotations.TypeDef;  
    133. import org.hibernate.annotations.TypeDefs;  
    134. import org.hibernate.annotations.Where;  
    135. import org.hibernate.annotations.common.reflection.ReflectionManager;  
    136. import org.hibernate.annotations.common.reflection.XAnnotatedElement;  
    137. import org.hibernate.annotations.common.reflection.XClass;  
    138. import org.hibernate.annotations.common.reflection.XMethod;  
    139. import org.hibernate.annotations.common.reflection.XPackage;  
    140. import org.hibernate.annotations.common.reflection.XProperty;  
    141. import org.hibernate.cache.RegionFactory;  
    142. import org.hibernate.cfg.annotations.CollectionBinder;  
    143. import org.hibernate.cfg.annotations.EntityBinder;  
    144. import org.hibernate.cfg.annotations.MapKeyColumnDelegator;  
    145. import org.hibernate.cfg.annotations.MapKeyJoinColumnDelegator;  
    146. import org.hibernate.cfg.annotations.Nullability;  
    147. import org.hibernate.cfg.annotations.PropertyBinder;  
    148. import org.hibernate.cfg.annotations.QueryBinder;  
    149. import org.hibernate.cfg.annotations.SimpleValueBinder;  
    150. import org.hibernate.cfg.annotations.TableBinder;  
    151. import org.hibernate.engine.FilterDefinition;  
    152. import org.hibernate.engine.Versioning;  
    153. import org.hibernate.id.MultipleHiLoPerTableGenerator;  
    154. import org.hibernate.id.PersistentIdentifierGenerator;  
    155. import org.hibernate.id.SequenceHiLoGenerator;  
    156. import org.hibernate.id.TableHiLoGenerator;  
    157. import org.hibernate.id.enhanced.SequenceStyleGenerator;  
    158. import org.hibernate.mapping.Any;  
    159. import org.hibernate.mapping.Component;  
    160. import org.hibernate.mapping.DependantValue;  
    161. import org.hibernate.mapping.IdGenerator;  
    162. import org.hibernate.mapping.Join;  
    163. import org.hibernate.mapping.JoinedSubclass;  
    164. import org.hibernate.mapping.KeyValue;  
    165. import org.hibernate.mapping.PersistentClass;  
    166. import org.hibernate.mapping.Property;  
    167. import org.hibernate.mapping.RootClass;  
    168. import org.hibernate.mapping.SimpleValue;  
    169. import org.hibernate.mapping.SingleTableSubclass;  
    170. import org.hibernate.mapping.Subclass;  
    171. import org.hibernate.mapping.ToOne;  
    172. import org.hibernate.mapping.UnionSubclass;  
    173. import org.hibernate.persister.entity.JoinedSubclassEntityPersister;  
    174. import org.hibernate.persister.entity.SingleTableEntityPersister;  
    175. import org.hibernate.persister.entity.UnionSubclassEntityPersister;  
    176.   
    177. /** 
    178.  * JSR 175 annotation binder which reads the annotations from classes, applies the 
    179.  * principles of the EJB3 spec and produces the Hibernate configuration-time metamodel 
    180.  * (the classes in the {@code org.hibernate.mapping} package) 
    181.  * 
    182.  * @author Emmanuel Bernard 
    183.  * @author Hardy Ferentschik 
    184.  */  
    185. @SuppressWarnings("unchecked")  
    186. public final class AnnotationBinder {  
    187.   
    188.     /* 
    189.      * Some design description 
    190.      * I tried to remove any link to annotation except from the 2 first level of 
    191.      * method call. 
    192.      * It'll enable to: 
    193.      *   - facilitate annotation overriding 
    194.      *   - mutualize one day xml and annotation binder (probably a dream though) 
    195.      *   - split this huge class in smaller mapping oriented classes 
    196.      * 
    197.      * bindSomething usually create the mapping container and is accessed by one of the 2 first level method 
    198.      * makeSomething usually create the mapping container and is accessed by bindSomething[else] 
    199.      * fillSomething take the container into parameter and fill it. 
    200.      */  
    201.   
    202.     private AnnotationBinder() {  
    203.     }  
    204.   
    205.     private static final Logger log = LoggerFactory.getLogger( AnnotationBinder.class );  
    206.   
    207.     public static void bindDefaults(Mappings mappings) {  
    208.         Map defaults = mappings.getReflectionManager().getDefaults();  
    209.         {  
    210.             List<SequenceGenerator> anns = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );  
    211.             if ( anns != null ) {  
    212.                 for ( SequenceGenerator ann : anns ) {  
    213.                     IdGenerator idGen = buildIdGenerator( ann, mappings );  
    214.                     if ( idGen != null ) {  
    215.                         mappings.addDefaultGenerator( idGen );  
    216.                     }  
    217.                 }  
    218.             }  
    219.         }  
    220.         {  
    221.             List<TableGenerator> anns = ( List<TableGenerator> ) defaults.get( TableGenerator.class );  
    222.             if ( anns != null ) {  
    223.                 for ( TableGenerator ann : anns ) {  
    224.                     IdGenerator idGen = buildIdGenerator( ann, mappings );  
    225.                     if ( idGen != null ) {  
    226.                         mappings.addDefaultGenerator( idGen );  
    227.                     }  
    228.                 }  
    229.             }  
    230.         }  
    231.         {  
    232.             List<NamedQuery> anns = ( List<NamedQuery> ) defaults.get( NamedQuery.class );  
    233.             if ( anns != null ) {  
    234.                 for ( NamedQuery ann : anns ) {  
    235.                     QueryBinder.bindQuery( ann, mappings, true );  
    236.                 }  
    237.             }  
    238.         }  
    239.         {  
    240.             List<NamedNativeQuery> anns = ( List<NamedNativeQuery> ) defaults.get( NamedNativeQuery.class );  
    241.             if ( anns != null ) {  
    242.                 for ( NamedNativeQuery ann : anns ) {  
    243.                     QueryBinder.bindNativeQuery( ann, mappings, true );  
    244.                 }  
    245.             }  
    246.         }  
    247.         {  
    248.             List<SqlResultSetMapping> anns = ( List<SqlResultSetMapping> ) defaults.get( SqlResultSetMapping.class );  
    249.             if ( anns != null ) {  
    250.                 for ( SqlResultSetMapping ann : anns ) {  
    251.                     QueryBinder.bindSqlResultsetMapping( ann, mappings, true );  
    252.                 }  
    253.             }  
    254.         }  
    255.     }  
    256.   
    257.     public static void bindPackage(String packageName, Mappings mappings) {  
    258.         XPackage pckg;  
    259.         try {  
    260.             pckg = mappings.getReflectionManager().packageForName( packageName );  
    261.         }  
    262.         catch ( ClassNotFoundException cnf ) {  
    263.             log.warn( "Package not found or wo package-info.java: {}", packageName );  
    264.             return;  
    265.         }  
    266.         if ( pckg.isAnnotationPresent( SequenceGenerator.class ) ) {  
    267.             SequenceGenerator ann = pckg.getAnnotation( SequenceGenerator.class );  
    268.             IdGenerator idGen = buildIdGenerator( ann, mappings );  
    269.             mappings.addGenerator( idGen );  
    270.             log.trace( "Add sequence generator with name: {}", idGen.getName() );  
    271.         }  
    272.         if ( pckg.isAnnotationPresent( TableGenerator.class ) ) {  
    273.             TableGenerator ann = pckg.getAnnotation( TableGenerator.class );  
    274.             IdGenerator idGen = buildIdGenerator( ann, mappings );  
    275.             mappings.addGenerator( idGen );  
    276.   
    277.         }  
    278.         bindGenericGenerators( pckg, mappings );  
    279.         bindQueries( pckg, mappings );  
    280.         bindFilterDefs( pckg, mappings );  
    281.         bindTypeDefs( pckg, mappings );  
    282.         bindFetchProfiles( pckg, mappings );  
    283.         BinderHelper.bindAnyMetaDefs( pckg, mappings );  
    284.           
    285.     }  
    286.   
    287.     private static void bindGenericGenerators(XAnnotatedElement annotatedElement, Mappings mappings) {  
    288.         GenericGenerator defAnn = annotatedElement.getAnnotation( GenericGenerator.class );  
    289.         GenericGenerators defsAnn = annotatedElement.getAnnotation( GenericGenerators.class );  
    290.         if ( defAnn != null ) {  
    291.             bindGenericGenerator( defAnn, mappings );  
    292.         }  
    293.         if ( defsAnn != null ) {  
    294.             for ( GenericGenerator def : defsAnn.value() ) {  
    295.                 bindGenericGenerator( def, mappings );  
    296.             }  
    297.         }  
    298.     }  
    299.   
    300.     private static void bindGenericGenerator(GenericGenerator def, Mappings mappings) {  
    301.         IdGenerator idGen = buildIdGenerator( def, mappings );  
    302.         mappings.addGenerator( idGen );  
    303.     }  
    304.   
    305.     private static void bindQueries(XAnnotatedElement annotatedElement, Mappings mappings) {  
    306.         {  
    307.             SqlResultSetMapping ann = annotatedElement.getAnnotation( SqlResultSetMapping.class );  
    308.             QueryBinder.bindSqlResultsetMapping( ann, mappings, false );  
    309.         }  
    310.         {  
    311.             SqlResultSetMappings ann = annotatedElement.getAnnotation( SqlResultSetMappings.class );  
    312.             if ( ann != null ) {  
    313.                 for ( SqlResultSetMapping current : ann.value() ) {  
    314.                     QueryBinder.bindSqlResultsetMapping( current, mappings, false );  
    315.                 }  
    316.             }  
    317.         }  
    318.         {  
    319.             NamedQuery ann = annotatedElement.getAnnotation( NamedQuery.class );  
    320.             QueryBinder.bindQuery( ann, mappings, false );  
    321.         }  
    322.         {  
    323.             org.hibernate.annotations.NamedQuery ann = annotatedElement.getAnnotation(  
    324.                     org.hibernate.annotations.NamedQuery.class  
    325.             );  
    326.             QueryBinder.bindQuery( ann, mappings );  
    327.         }  
    328.         {  
    329.             NamedQueries ann = annotatedElement.getAnnotation( NamedQueries.class );  
    330.             QueryBinder.bindQueries( ann, mappings, false );  
    331.         }  
    332.         {  
    333.             org.hibernate.annotations.NamedQueries ann = annotatedElement.getAnnotation(  
    334.                     org.hibernate.annotations.NamedQueries.class  
    335.             );  
    336.             QueryBinder.bindQueries( ann, mappings );  
    337.         }  
    338.         {  
    339.             NamedNativeQuery ann = annotatedElement.getAnnotation( NamedNativeQuery.class );  
    340.             QueryBinder.bindNativeQuery( ann, mappings, false );  
    341.         }  
    342.         {  
    343.             org.hibernate.annotations.NamedNativeQuery ann = annotatedElement.getAnnotation(  
    344.                     org.hibernate.annotations.NamedNativeQuery.class  
    345.             );  
    346.             QueryBinder.bindNativeQuery( ann, mappings );  
    347.         }  
    348.         {  
    349.             NamedNativeQueries ann = annotatedElement.getAnnotation( NamedNativeQueries.class );  
    350.             QueryBinder.bindNativeQueries( ann, mappings, false );  
    351.         }  
    352.         {  
    353.             org.hibernate.annotations.NamedNativeQueries ann = annotatedElement.getAnnotation(  
    354.                     org.hibernate.annotations.NamedNativeQueries.class  
    355.             );  
    356.             QueryBinder.bindNativeQueries( ann, mappings );  
    357.         }  
    358.     }  
    359.   
    360.     private static IdGenerator buildIdGenerator(java.lang.annotation.Annotation ann, Mappings mappings) {  
    361.         IdGenerator idGen = new IdGenerator();  
    362.         if ( mappings.getSchemaName() != null ) {  
    363.             idGen.addParam( PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName() );  
    364.         }  
    365.         if ( mappings.getCatalogName() != null ) {  
    366.             idGen.addParam( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() );  
    367.         }  
    368.         final boolean useNewGeneratorMappings = mappings.useNewGeneratorMappings();  
    369.         if ( ann == null ) {  
    370.             idGen = null;  
    371.         }  
    372.         else if ( ann instanceof TableGenerator ) {  
    373.             TableGenerator tabGen = ( TableGenerator ) ann;  
    374.             idGen.setName( tabGen.name() );  
    375.             if ( useNewGeneratorMappings ) {  
    376.                 idGen.setIdentifierGeneratorStrategy( org.hibernate.id.enhanced.TableGenerator.class.getName() );  
    377.                 idGen.addParam( org.hibernate.id.enhanced.TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" );  
    378.   
    379.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.catalog() ) ) {  
    380.                     idGen.addParam( org.hibernate.id.enhanced.TableGenerator.CATALOG, tabGen.catalog() );  
    381.                 }  
    382.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.schema() ) ) {  
    383.                     idGen.addParam( org.hibernate.id.enhanced.TableGenerator.SCHEMA, tabGen.schema() );  
    384.                 }  
    385.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.table() ) ) {  
    386.                     idGen.addParam( org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM, tabGen.table() );  
    387.                 }  
    388.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnName() ) ) {  
    389.                     idGen.addParam(  
    390.                             org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM, tabGen.pkColumnName()  
    391.                     );  
    392.                 }  
    393.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnValue() ) ) {  
    394.                     idGen.addParam(  
    395.                             org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM, tabGen.pkColumnValue()  
    396.                     );  
    397.                 }  
    398.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.valueColumnName() ) ) {  
    399.                     idGen.addParam(  
    400.                             org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM, tabGen.valueColumnName()  
    401.                     );  
    402.                 }  
    403.                 idGen.addParam(  
    404.                         org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM,  
    405.                         String.valueOf( tabGen.allocationSize() )  
    406.                 );  
    407.                 // See comment on HHH-4884 wrt initialValue.  Basically initialValue is really the stated value + 1  
    408.                 idGen.addParam(  
    409.                         org.hibernate.id.enhanced.TableGenerator.INITIAL_PARAM,  
    410.                         String.valueOf( tabGen.initialValue() + 1 )  
    411.                 );  
    412.                 if ( tabGen.uniqueConstraints() != null && tabGen.uniqueConstraints().length > 0 ) {  
    413.                     log.warn( "Ignoring unique constraints specified on table generator [{}]", tabGen.name() );  
    414.                 }  
    415.             }  
    416.             else {  
    417.                 idGen.setIdentifierGeneratorStrategy( MultipleHiLoPerTableGenerator.class.getName() );  
    418.   
    419.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.table() ) ) {  
    420.                     idGen.addParam( MultipleHiLoPerTableGenerator.ID_TABLE, tabGen.table() );  
    421.                 }  
    422.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.catalog() ) ) {  
    423.                     idGen.addParam( MultipleHiLoPerTableGenerator.CATALOG, tabGen.catalog() );  
    424.                 }  
    425.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.schema() ) ) {  
    426.                     idGen.addParam( MultipleHiLoPerTableGenerator.SCHEMA, tabGen.schema() );  
    427.                 }  
    428.                 //FIXME implement uniqueconstrains  
    429.                 if ( tabGen.uniqueConstraints() != null && tabGen.uniqueConstraints().length > 0 ) {  
    430.                     log.warn( "Ignoring unique constraints specified on table generator [{}]", tabGen.name() );  
    431.                 }  
    432.   
    433.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnName() ) ) {  
    434.                     idGen.addParam( MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, tabGen.pkColumnName() );  
    435.                 }  
    436.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.valueColumnName() ) ) {  
    437.                     idGen.addParam( MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, tabGen.valueColumnName() );  
    438.                 }  
    439.                 if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnValue() ) ) {  
    440.                     idGen.addParam( MultipleHiLoPerTableGenerator.PK_VALUE_NAME, tabGen.pkColumnValue() );  
    441.                 }  
    442.                 idGen.addParam( TableHiLoGenerator.MAX_LO, String.valueOf( tabGen.allocationSize() - 1 ) );  
    443.             }  
    444.             log.trace( "Add table generator with name: {}", idGen.getName() );  
    445.         }  
    446.         else if ( ann instanceof SequenceGenerator ) {  
    447.             SequenceGenerator seqGen = ( SequenceGenerator ) ann;  
    448.             idGen.setName( seqGen.name() );  
    449.             if ( useNewGeneratorMappings ) {  
    450.                 idGen.setIdentifierGeneratorStrategy( SequenceStyleGenerator.class.getName() );  
    451.   
    452.                 if ( !BinderHelper.isEmptyAnnotationValue( seqGen.catalog() ) ) {  
    453.                     idGen.addParam( SequenceStyleGenerator.CATALOG, seqGen.catalog() );  
    454.                 }  
    455.                 if ( !BinderHelper.isEmptyAnnotationValue( seqGen.schema() ) ) {  
    456.                     idGen.addParam( SequenceStyleGenerator.SCHEMA, seqGen.schema() );  
    457.                 }  
    458.                 if ( !BinderHelper.isEmptyAnnotationValue( seqGen.sequenceName() ) ) {  
    459.                     idGen.addParam( SequenceStyleGenerator.SEQUENCE_PARAM, seqGen.sequenceName() );  
    460.                 }  
    461.                 idGen.addParam( SequenceStyleGenerator.INCREMENT_PARAM, String.valueOf( seqGen.allocationSize() ) );  
    462.                 idGen.addParam( SequenceStyleGenerator.INITIAL_PARAM, String.valueOf( seqGen.initialValue() ) );  
    463.             }  
    464.             else {  
    465.                 idGen.setIdentifierGeneratorStrategy( "seqhilo" );  
    466.   
    467.                 if ( !BinderHelper.isEmptyAnnotationValue( seqGen.sequenceName() ) ) {  
    468.                     idGen.addParam( org.hibernate.id.SequenceGenerator.SEQUENCE, seqGen.sequenceName() );  
    469.                 }  
    470.                 //FIXME: work on initialValue() through SequenceGenerator.PARAMETERS  
    471.                 //      steve : or just use o.h.id.enhanced.SequenceStyleGenerator  
    472.                 if ( seqGen.initialValue() != 1 ) {  
    473.                     log.warn(  
    474.                             "Hibernate does not support SequenceGenerator.initialValue() unless '{}' set",  
    475.                             Configuration.USE_NEW_ID_GENERATOR_MAPPINGS  
    476.                     );  
    477.                 }  
    478.                 idGen.addParam( SequenceHiLoGenerator.MAX_LO, String.valueOf( seqGen.allocationSize() - 1 ) );  
    479.                 log.trace( "Add sequence generator with name: {}", idGen.getName() );  
    480.             }  
    481.         }  
    482.         else if ( ann instanceof GenericGenerator ) {  
    483.             GenericGenerator genGen = ( GenericGenerator ) ann;  
    484.             idGen.setName( genGen.name() );  
    485.             idGen.setIdentifierGeneratorStrategy( genGen.strategy() );  
    486.             Parameter[] params = genGen.parameters();  
    487.             for ( Parameter parameter : params ) {  
    488.                 idGen.addParam( parameter.name(), parameter.value() );  
    489.             }  
    490.             log.trace( "Add generic generator with name: {}", idGen.getName() );  
    491.         }  
    492.         else {  
    493.             throw new AssertionFailure( "Unknown Generator annotation: " + ann );  
    494.         }  
    495.         return idGen;  
    496.     }  
    497.   
    498.     /** 
    499.      * Bind a class having JSR175 annotations. Subclasses <b>have to</b> be bound after its parent class. 
    500.      * 
    501.      * @param clazzToProcess entity to bind as {@code XClass} instance 
    502.      * @param inheritanceStatePerClass Meta data about the inheritance relationships for all mapped classes 
    503.      * @param mappings Mapping meta data 
    504.      * 
    505.      * @throws MappingException in case there is an configuration error 
    506.      */  
    507.     public static void bindClass(  
    508.             XClass clazzToProcess,  
    509.             Map<XClass, InheritanceState> inheritanceStatePerClass,  
    510.             Mappings mappings) throws MappingException {  
    511.         //@Entity and @MappedSuperclass on the same class leads to a NPE down the road  
    512.         if ( clazzToProcess.isAnnotationPresent( Entity.class )   
    513.                 &&  clazzToProcess.isAnnotationPresent( MappedSuperclass.class ) ) {  
    514.             throw new AnnotationException( "An entity cannot be annotated with both @Entity and @MappedSuperclass: "  
    515.                     + clazzToProcess.getName() );  
    516.         }  
    517.   
    518.         //TODO: be more strict with secondarytable allowance (not for ids, not for secondary table join columns etc)  
    519.         InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );  
    520.         AnnotatedClassType classType = mappings.getClassType( clazzToProcess );  
    521.   
    522.         //Queries declared in MappedSuperclass should be usable in Subclasses  
    523.         if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) ) {  
    524.             bindQueries( clazzToProcess, mappings );  
    525.             bindTypeDefs( clazzToProcess, mappings );  
    526.             bindFilterDefs( clazzToProcess, mappings );  
    527.         }  
    528.   
    529.         if ( !isEntityClassType( clazzToProcess, classType ) ) {  
    530.             return;  
    531.         }  
    532.   
    533.         log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() );  
    534.   
    535.         PersistentClass superEntity = getSuperEntity(  
    536.                 clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState  
    537.         );  
    538.   
    539.         PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );  
    540.         Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );  
    541.         org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(  
    542.                 org.hibernate.annotations.Entity.class  
    543.         );  
    544.         EntityBinder entityBinder = new EntityBinder(  
    545.                 entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings  
    546.         );  
    547.         entityBinder.setInheritanceState( inheritanceState );  
    548.   
    549.         bindQueries( clazzToProcess, mappings );  
    550.         bindFilterDefs( clazzToProcess, mappings );  
    551.         bindTypeDefs( clazzToProcess, mappings );  
    552.         bindFetchProfiles( clazzToProcess, mappings );  
    553.         BinderHelper.bindAnyMetaDefs( clazzToProcess, mappings );  
    554.           
    555.           
    556.         String schema = "";  
    557.         String table = ""; //might be no @Table annotation on the annotated class  
    558.         String catalog = "";  
    559.         List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();  
    560.         if ( clazzToProcess.isAnnotationPresent( javax.persistence.Table.class ) ) {  
    561.             javax.persistence.Table tabAnn = clazzToProcess.getAnnotation( javax.persistence.Table.class );  
    562.             table = tabAnn.name();  
    563.             schema = tabAnn.schema();  
    564.             catalog = tabAnn.catalog();  
    565.             uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );  
    566.         }  
    567.   
    568.         Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(  
    569.                 clazzToProcess, mappings, inheritanceState, superEntity  
    570.         );  
    571.         Ejb3DiscriminatorColumn discriminatorColumn = null;  
    572.         if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {  
    573.             discriminatorColumn = processDiscriminatorProperties(  
    574.                     clazzToProcess, mappings, inheritanceState, entityBinder  
    575.             );  
    576.         }  
    577.   
    578.         entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );  
    579.         entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );  
    580.         entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );  
    581.         entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );  
    582.   
    583.         //Filters are not allowed on subclasses  
    584.         if ( !inheritanceState.hasParents() ) {  
    585.             bindFilters( clazzToProcess, entityBinder, mappings );  
    586.         }  
    587.   
    588.         entityBinder.bindEntity();  
    589.   
    590.         if ( inheritanceState.hasTable() ) {  
    591.             Check checkAnn = clazzToProcess.getAnnotation( Check.class );  
    592.             String constraints = checkAnn == null ?  
    593.                     null :  
    594.                     checkAnn.constraints();  
    595.             entityBinder.bindTable(  
    596.                     schema, catalog, table, uniqueConstraints,  
    597.                     constraints, inheritanceState.hasDenormalizedTable() ?  
    598.                             superEntity.getTable() :  
    599.                             null  
    600.             );  
    601.         }  
    602.         else {  
    603.             if ( clazzToProcess.isAnnotationPresent( Table.class ) ) {  
    604.                 log.warn(  
    605.                         "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess  
    606.                                 .getName()  
    607.                 );  
    608.             }  
    609.         }  
    610.   
    611.         PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(  
    612.                 clazzToProcess,  
    613.                 persistentClass,  
    614.                 entityBinder, mappings, inheritanceStatePerClass  
    615.         );  
    616.   
    617.         javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation(  
    618.                 javax.persistence.SecondaryTable.class  
    619.         );  
    620.         javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation(  
    621.                 javax.persistence.SecondaryTables.class  
    622.         );  
    623.         entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn );  
    624.   
    625.         OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );  
    626.         boolean onDeleteAppropriate = false;  
    627.         if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) {  
    628.             onDeleteAppropriate = true;  
    629.             final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass;  
    630.             if ( persistentClass.getEntityPersisterClass() == null ) {  
    631.                 persistentClass.getRootClass().setEntityPersisterClass( JoinedSubclassEntityPersister.class );  
    632.             }  
    633.             SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() );  
    634.             jsc.setKey( key );  
    635.             ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class );  
    636.             if ( fk != null && !BinderHelper.isEmptyAnnotationValue( fk.name() ) ) {  
    637.                 key.setForeignKeyName( fk.name() );  
    638.             }  
    639.             if ( onDeleteAnn != null ) {  
    640.                 key.setCascadeDeleteEnabled( OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) );  
    641.             }  
    642.             else {  
    643.                 key.setCascadeDeleteEnabled( false );  
    644.             }  
    645.             //we are never in a second pass at that stage, so queue it  
    646.             SecondPass sp = new JoinedSubclassFkSecondPass( jsc, inheritanceJoinedColumns, key, mappings );  
    647.             mappings.addSecondPass( sp );  
    648.             mappings.addSecondPass( new CreateKeySecondPass( jsc ) );  
    649.   
    650.         }  
    651.         else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {  
    652.             if ( inheritanceState.hasParents() ) {  
    653.                 if ( persistentClass.getEntityPersisterClass() == null ) {  
    654.                     persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class );  
    655.                 }  
    656.             }  
    657.             else {  
    658.                 if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) {  
    659.                     //need a discriminator column  
    660.                     bindDiscriminatorToPersistentClass(  
    661.                             ( RootClass ) persistentClass,  
    662.                             discriminatorColumn,  
    663.                             entityBinder.getSecondaryTables(),  
    664.                             propertyHolder,  
    665.                             mappings  
    666.                     );  
    667.                     entityBinder.bindDiscriminatorValue();//bind it again since the type might have changed  
    668.                 }  
    669.             }  
    670.         }  
    671.         else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {  
    672.             if ( inheritanceState.hasParents() ) {  
    673.                 if ( persistentClass.getEntityPersisterClass() == null ) {  
    674.                     persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class );  
    675.                 }  
    676.             }  
    677.         }  
    678.         if ( onDeleteAnn != null && !onDeleteAppropriate ) {  
    679.             log.warn(  
    680.                     "Inapropriate use of @OnDelete on entity, annotation ignored: {}", propertyHolder.getEntityName()  
    681.             );  
    682.         }  
    683.   
    684.         // try to find class level generators  
    685.         HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );  
    686.   
    687.         // check properties  
    688.         final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState.getElementsToProcess();  
    689.         inheritanceState.postProcess( persistentClass, entityBinder );  
    690.   
    691.         final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE  
    692.                 && inheritanceState.hasParents();  
    693.         Set<String> idPropertiesIfIdClass = new HashSet<String>();  
    694.         boolean isIdClass = mapAsIdClass(  
    695.                 inheritanceStatePerClass,  
    696.                 inheritanceState,  
    697.                 persistentClass,  
    698.                 entityBinder,  
    699.                 propertyHolder,  
    700.                 elementsToProcess,  
    701.                 idPropertiesIfIdClass,  
    702.                 mappings  
    703.         );  
    704.   
    705.         if ( !isIdClass ) {  
    706.             entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );  
    707.         }  
    708.   
    709.         processIdPropertiesIfNotAlready(  
    710.                 inheritanceStatePerClass,  
    711.                 mappings,  
    712.                 persistentClass,  
    713.                 entityBinder,  
    714.                 propertyHolder,  
    715.                 classGenerators,  
    716.                 elementsToProcess,  
    717.                 subclassAndSingleTableStrategy,  
    718.                 idPropertiesIfIdClass  
    719.         );  
    720.   
    721.         if ( !inheritanceState.hasParents() ) {  
    722.             final RootClass rootClass = ( RootClass ) persistentClass;  
    723.             mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );  
    724.         }  
    725.         else {  
    726.             superEntity.addSubclass( ( Subclass ) persistentClass );  
    727.         }  
    728.   
    729.         mappings.addClass( persistentClass );  
    730.   
    731.         //Process secondary tables and complementary definitions (ie o.h.a.Table)  
    732.         mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );  
    733.   
    734.         //add process complementary Table definition (index & all)  
    735.         entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );  
    736.         entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );  
    737.           
    738.         CommentBinder.bindTableComment(clazzToProcess, persistentClass);//绑定表名注释  
    739.           
    740.   
    741.     }  
    742.   
    743.     // parse everything discriminator column relevant in case of single table inheritance  
    744.     private static Ejb3DiscriminatorColumn processDiscriminatorProperties(XClass clazzToProcess, Mappings mappings, InheritanceState inheritanceState, EntityBinder entityBinder) {  
    745.         Ejb3DiscriminatorColumn discriminatorColumn = null;  
    746.         javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(  
    747.                 javax.persistence.DiscriminatorColumn.class  
    748.         );  
    749.         DiscriminatorType discriminatorType = discAnn != null ?  
    750.                 discAnn.discriminatorType() :  
    751.                 DiscriminatorType.STRING;  
    752.   
    753.         org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(  
    754.                 org.hibernate.annotations.DiscriminatorFormula.class  
    755.         );  
    756.         if ( !inheritanceState.hasParents() ) {  
    757.             discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(  
    758.                     discriminatorType, discAnn, discFormulaAnn, mappings  
    759.             );  
    760.         }  
    761.         if ( discAnn != null && inheritanceState.hasParents() ) {  
    762.             log.warn(  
    763.                     "Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",  
    764.                     clazzToProcess.getName()  
    765.             );  
    766.         }  
    767.   
    768.         String discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?  
    769.                 clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :  
    770.                 null;  
    771.         entityBinder.setDiscriminatorValue( discrimValue );  
    772.   
    773.         if ( clazzToProcess.isAnnotationPresent( ForceDiscriminator.class ) ) {  
    774.             log.warn( "@ForceDiscriminator is deprecated use @DiscriminatorOptions instead." );  
    775.             entityBinder.setForceDiscriminator( true );  
    776.         }  
    777.   
    778.         DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );  
    779.         if ( discriminatorOptions != null) {  
    780.             entityBinder.setForceDiscriminator( discriminatorOptions.force() );  
    781.             entityBinder.setInsertableDiscriminator( discriminatorOptions.insert() );  
    782.         }  
    783.   
    784.         return discriminatorColumn;  
    785.     }  
    786.   
    787.     private static void processIdPropertiesIfNotAlready(  
    788.             Map<XClass, InheritanceState> inheritanceStatePerClass,  
    789.             Mappings mappings,  
    790.             PersistentClass persistentClass,  
    791.             EntityBinder entityBinder,  
    792.             PropertyHolder propertyHolder,  
    793.             HashMap<String, IdGenerator> classGenerators,  
    794.             InheritanceState.ElementsToProcess elementsToProcess,  
    795.             boolean subclassAndSingleTableStrategy,  
    796.             Set<String> idPropertiesIfIdClass) {  
    797.         Set<String> missingIdProperties = new HashSet<String>( idPropertiesIfIdClass );  
    798.         for ( PropertyData propertyAnnotatedElement : elementsToProcess.getElements() ) {  
    799.             String propertyName = propertyAnnotatedElement.getPropertyName();  
    800.             if ( !idPropertiesIfIdClass.contains( propertyName ) ) {  
    801.                 processElementAnnotations(  
    802.                         propertyHolder,  
    803.                         subclassAndSingleTableStrategy ?  
    804.                                 Nullability.FORCED_NULL :  
    805.                                 Nullability.NO_CONSTRAINT,  
    806.                         propertyAnnotatedElement, classGenerators, entityBinder,  
    807.                         false, false, false, mappings, inheritanceStatePerClass  
    808.                 );  
    809.             }  
    810.             else {  
    811.                 missingIdProperties.remove( propertyName );  
    812.             }  
    813.         }  
    814.   
    815.         if ( missingIdProperties.size() != 0 ) {  
    816.             StringBuilder missings = new StringBuilder();  
    817.             for ( String property : missingIdProperties ) {  
    818.                 missings.append( property ).append( ", " );  
    819.             }  
    820.             throw new AnnotationException(  
    821.                     "Unable to find properties ("  
    822.                             + missings.substring( 0, missings.length() - 2 )  
    823.                             + ") in entity annotated with @IdClass:" + persistentClass.getEntityName()  
    824.             );  
    825.         }  
    826.     }  
    827.   
    828.     private static boolean mapAsIdClass(  
    829.             Map<XClass, InheritanceState> inheritanceStatePerClass,  
    830.             InheritanceState inheritanceState,  
    831.             PersistentClass persistentClass,  
    832.             EntityBinder entityBinder,  
    833.             PropertyHolder propertyHolder,  
    834.             InheritanceState.ElementsToProcess elementsToProcess,  
    835.             Set<String> idPropertiesIfIdClass,  
    836.             Mappings mappings) {  
    837.         /* 
    838.          * We are looking for @IdClass 
    839.          * In general we map the id class as identifier using the mapping metadata of the main entity's properties 
    840.          * and we create an identifier mapper containing the id properties of the main entity 
    841.          * 
    842.          * In JPA 2, there is a shortcut if the id class is the Pk of the associated class pointed to by the id 
    843.          * it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way 
    844.          */  
    845.         XClass classWithIdClass = inheritanceState.getClassWithIdClass( false );  
    846.         if ( classWithIdClass != null ) {  
    847.             IdClass idClass = classWithIdClass.getAnnotation( IdClass.class );  
    848.             XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );  
    849.             PropertyData inferredData = new PropertyPreloadedData(  
    850.                     entityBinder.getPropertyAccessType(), "id", compositeClass  
    851.             );  
    852.             PropertyData baseInferredData = new PropertyPreloadedData(  
    853.                     entityBinder.getPropertyAccessType(), "id", classWithIdClass  
    854.             );  
    855.             AccessType propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );  
    856.             //In JPA 2, there is a shortcut if the IdClass is the Pk of the associated class pointed to by the id  
    857.             //it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way  
    858.             final boolean isFakeIdClass = isIdClassPkOfTheAssociatedEntity(  
    859.                     elementsToProcess,  
    860.                     compositeClass,  
    861.                     inferredData,  
    862.                     baseInferredData,  
    863.                     propertyAccessor,  
    864.                     inheritanceStatePerClass,  
    865.                     mappings  
    866.             );  
    867.   
    868.             if ( isFakeIdClass ) {  
    869.                 return false;  
    870.             }  
    871.   
    872.             boolean isComponent = true;  
    873.             String generatorType = "assigned";  
    874.             String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;  
    875.   
    876.             boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();  
    877.             entityBinder.setIgnoreIdAnnotations( true );  
    878.             propertyHolder.setInIdClass( true );  
    879.             bindIdClass(  
    880.                     generatorType,  
    881.                     generator,  
    882.                     inferredData,  
    883.                     baseInferredData,  
    884.                     null,  
    885.                     propertyHolder,  
    886.                     isComponent,  
    887.                     propertyAccessor,  
    888.                     entityBinder,  
    889.                     true,  
    890.                     false,  
    891.                     mappings,  
    892.                     inheritanceStatePerClass  
    893.             );  
    894.             propertyHolder.setInIdClass( null );  
    895.             inferredData = new PropertyPreloadedData(  
    896.                     propertyAccessor, "_identifierMapper", compositeClass  
    897.             );  
    898.             Component mapper = fillComponent(  
    899.                     propertyHolder,  
    900.                     inferredData,  
    901.                     baseInferredData,  
    902.                     propertyAccessor,  
    903.                     false,  
    904.                     entityBinder,  
    905.                     true,  
    906.                     true,  
    907.                     false,  
    908.                     mappings,  
    909.                     inheritanceStatePerClass  
    910.             );  
    911.             entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );  
    912.             persistentClass.setIdentifierMapper( mapper );  
    913.   
    914.             //If id definition is on a mapped superclass, update the mapping  
    915.             final org.hibernate.mapping.MappedSuperclass superclass =  
    916.                     BinderHelper.getMappedSuperclassOrNull(  
    917.                             inferredData.getDeclaringClass(),  
    918.                             inheritanceStatePerClass,  
    919.                             mappings  
    920.                     );  
    921.             if ( superclass != null ) {  
    922.                 superclass.setDeclaredIdentifierMapper( mapper );  
    923.             }  
    924.             else {  
    925.                 //we are for sure on the entity  
    926.                 persistentClass.setDeclaredIdentifierMapper( mapper );  
    927.             }  
    928.   
    929.             Property property = new Property();  
    930.             property.setName( "_identifierMapper" );  
    931.             property.setNodeName( "id" );  
    932.             property.setUpdateable( false );  
    933.             property.setInsertable( false );  
    934.             property.setValue( mapper );  
    935.             property.setPropertyAccessorName( "embedded" );  
    936.             persistentClass.addProperty( property );  
    937.             entityBinder.setIgnoreIdAnnotations( true );  
    938.   
    939.             Iterator properties = mapper.getPropertyIterator();  
    940.             while ( properties.hasNext() ) {  
    941.                 idPropertiesIfIdClass.add( ( ( Property ) properties.next() ).getName() );  
    942.             }  
    943.             return true;  
    944.         }  
    945.         else {  
    946.             return false;  
    947.         }  
    948.     }  
    949.   
    950.     private static boolean isIdClassPkOfTheAssociatedEntity(  
    951.             InheritanceState.ElementsToProcess elementsToProcess,  
    952.             XClass compositeClass,  
    953.             PropertyData inferredData,  
    954.             PropertyData baseInferredData,  
    955.             AccessType propertyAccessor,  
    956.             Map<XClass, InheritanceState> inheritanceStatePerClass,  
    957.             Mappings mappings) {  
    958.         if ( elementsToProcess.getIdPropertyCount() == 1 ) {  
    959.             final PropertyData idPropertyOnBaseClass = getUniqueIdPropertyFromBaseClass(  
    960.                     inferredData, baseInferredData, propertyAccessor, mappings  
    961.             );  
    962.             final InheritanceState state = inheritanceStatePerClass.get( idPropertyOnBaseClass.getClassOrElement() );  
    963.             if ( state == null ) {  
    964.                 return false; //while it is likely a user error, let's consider it is something that might happen  
    965.             }  
    966.             final XClass associatedClassWithIdClass = state.getClassWithIdClass( true );  
    967.             if ( associatedClassWithIdClass == null ) {  
    968.                 //we cannot know for sure here unless we try and find the @EmbeddedId  
    969.                 //Let's not do this thorough checking but do some extra validation  
    970.                 final XProperty property = idPropertyOnBaseClass.getProperty();  
    971.                 return property.isAnnotationPresent( ManyToOne.class )  
    972.                         || property.isAnnotationPresent( OneToOne.class );  
    973.   
    974.             }  
    975.             else {  
    976.                 final XClass idClass = mappings.getReflectionManager().toXClass(  
    977.                         associatedClassWithIdClass.getAnnotation( IdClass.class ).value()  
    978.                 );  
    979.                 return idClass.equals( compositeClass );  
    980.             }  
    981.         }  
    982.         else {  
    983.             return false;  
    984.         }  
    985.     }  
    986.   
    987.     private static Cache determineCacheSettings(XClass clazzToProcess, Mappings mappings) {  
    988.         Cache cacheAnn = clazzToProcess.getAnnotation( Cache.class );  
    989.         if ( cacheAnn != null ) {  
    990.             return cacheAnn;  
    991.         }  
    992.   
    993.         Cacheable cacheableAnn = clazzToProcess.getAnnotation( Cacheable.class );  
    994.         SharedCacheMode mode = determineSharedCacheMode( mappings );  
    995.         switch ( mode ) {  
    996.             case ALL: {  
    997.                 cacheAnn = buildCacheMock( clazzToProcess.getName(), mappings );  
    998.                 break;  
    999.             }  
    1000.             case ENABLE_SELECTIVE: {  
    1001.                 if ( cacheableAnn != null && cacheableAnn.value() ) {  
    1002.                     cacheAnn = buildCacheMock( clazzToProcess.getName(), mappings );  
    1003.                 }  
    1004.                 break;  
    1005.             }  
    1006.             case DISABLE_SELECTIVE: {  
    1007.                 if ( cacheableAnn == null || cacheableAnn.value() ) {  
    1008.                     cacheAnn = buildCacheMock( clazzToProcess.getName(), mappings );  
    1009.                 }  
    1010.                 break;  
    1011.             }  
    1012.             default: {  
    1013.                 // treat both NONE and UNSPECIFIED the same  
    1014.                 break;  
    1015.             }  
    1016.         }  
    1017.         return cacheAnn;  
    1018.     }  
    1019.   
    1020.     private static SharedCacheMode determineSharedCacheMode(Mappings mappings) {  
    1021.         SharedCacheMode mode;  
    1022.         final Object value = mappings.getConfigurationProperties().get( "javax.persistence.sharedCache.mode" );  
    1023.         if ( value == null ) {  
    1024.             log.debug( "no value specified for 'javax.persistence.sharedCache.mode'; using UNSPECIFIED" );  
    1025.             mode = SharedCacheMode.UNSPECIFIED;  
    1026.         }  
    1027.         else {  
    1028.             if ( SharedCacheMode.class.isInstance( value ) ) {  
    1029.                 mode = ( SharedCacheMode ) value;  
    1030.             }  
    1031.             else {  
    1032.                 try {  
    1033.                     mode = SharedCacheMode.valueOf( value.toString() );  
    1034.                 }  
    1035.                 catch ( Exception e ) {  
    1036.                     log.debug(  
    1037.                             "Unable to resolve given mode name [" + value.toString()  
    1038.                                     + "]; using UNSPECIFIED : " + e.toString()  
    1039.                     );  
    1040.                     mode = SharedCacheMode.UNSPECIFIED;  
    1041.                 }  
    1042.             }  
    1043.         }  
    1044.         return mode;  
    1045.     }  
    1046.   
    1047.     private static Cache buildCacheMock(String region, Mappings mappings) {  
    1048.         return new LocalCacheAnnotationImpl( region, determineCacheConcurrencyStrategy( mappings ) );  
    1049.     }  
    1050.   
    1051.     private static CacheConcurrencyStrategy DEFAULT_CACHE_CONCURRENCY_STRATEGY;  
    1052.   
    1053.     static void prepareDefaultCacheConcurrencyStrategy(Properties properties) {  
    1054.         if ( DEFAULT_CACHE_CONCURRENCY_STRATEGY != null ) {  
    1055.             log.trace( "Default cache concurrency strategy already defined" );  
    1056.             return;  
    1057.         }  
    1058.   
    1059.         if ( !properties.containsKey( Configuration.DEFAULT_CACHE_CONCURRENCY_STRATEGY ) ) {  
    1060.             log.trace( "Given properties did not contain any default cache concurrency strategy setting" );  
    1061.             return;  
    1062.         }  
    1063.   
    1064.         final String strategyName = properties.getProperty( Configuration.DEFAULT_CACHE_CONCURRENCY_STRATEGY );  
    1065.         log.trace( "Discovered default cache concurrency strategy via config [" + strategyName + "]" );  
    1066.         CacheConcurrencyStrategy strategy = CacheConcurrencyStrategy.parse( strategyName );  
    1067.         if ( strategy == null ) {  
    1068.             log.trace( "Discovered default cache concurrency strategy specified nothing" );  
    1069.             return;  
    1070.         }  
    1071.   
    1072.         log.debug( "Setting default cache concurrency strategy via config [" + strategy.name() + "]" );  
    1073.         DEFAULT_CACHE_CONCURRENCY_STRATEGY = strategy;  
    1074.     }  
    1075.   
    1076.     private static CacheConcurrencyStrategy determineCacheConcurrencyStrategy(Mappings mappings) {  
    1077.         if ( DEFAULT_CACHE_CONCURRENCY_STRATEGY == null ) {  
    1078.             final RegionFactory cacheRegionFactory = SettingsFactory.createRegionFactory(  
    1079.                     mappings.getConfigurationProperties(), true  
    1080.             );  
    1081.             DEFAULT_CACHE_CONCURRENCY_STRATEGY = CacheConcurrencyStrategy.fromAccessType( cacheRegionFactory.getDefaultAccessType() );  
    1082.         }  
    1083.         return DEFAULT_CACHE_CONCURRENCY_STRATEGY;  
    1084.     }  
    1085.   
    1086.     @SuppressWarnings({ "ClassExplicitlyAnnotation" })  
    1087.     private static class LocalCacheAnnotationImpl implements Cache {  
    1088.         private final String region;  
    1089.         private final CacheConcurrencyStrategy usage;  
    1090.   
    1091.         private LocalCacheAnnotationImpl(String region, CacheConcurrencyStrategy usage) {  
    1092.             this.region = region;  
    1093.             this.usage = usage;  
    1094.         }  
    1095.   
    1096.         public CacheConcurrencyStrategy usage() {  
    1097.             return usage;  
    1098.         }  
    1099.   
    1100.         public String region() {  
    1101.             return region;  
    1102.         }  
    1103.   
    1104.         public String include() {  
    1105.             return "all";  
    1106.         }  
    1107.   
    1108.         public Class<? extends Annotation> annotationType() {  
    1109.             return Cache.class;  
    1110.         }  
    1111.     }  
    1112.   
    1113.     private static PersistentClass makePersistentClass(InheritanceState inheritanceState, PersistentClass superEntity) {  
    1114.         //we now know what kind of persistent entity it is  
    1115.         PersistentClass persistentClass;  
    1116.         //create persistent class  
    1117.         if ( !inheritanceState.hasParents() ) {  
    1118.             persistentClass = new RootClass();  
    1119.         }  
    1120.         else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {  
    1121.             persistentClass = new SingleTableSubclass( superEntity );  
    1122.         }  
    1123.         else if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) ) {  
    1124.             persistentClass = new JoinedSubclass( superEntity );  
    1125.         }  
    1126.         else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {  
    1127.             persistentClass = new UnionSubclass( superEntity );  
    1128.         }  
    1129.         else {  
    1130.             throw new AssertionFailure( "Unknown inheritance type: " + inheritanceState.getType() );  
    1131.         }  
    1132.         return persistentClass;  
    1133.     }  
    1134.   
    1135.     private static Ejb3JoinColumn[] makeInheritanceJoinColumns(  
    1136.             XClass clazzToProcess,  
    1137.             Mappings mappings,  
    1138.             InheritanceState inheritanceState,  
    1139.             PersistentClass superEntity) {  
    1140.         Ejb3JoinColumn[] inheritanceJoinedColumns = null;  
    1141.         final boolean hasJoinedColumns = inheritanceState.hasParents()  
    1142.                 && InheritanceType.JOINED.equals( inheritanceState.getType() );  
    1143.         if ( hasJoinedColumns ) {  
    1144.             //@Inheritance(JOINED) subclass need to link back to the super entity  
    1145.             PrimaryKeyJoinColumns jcsAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumns.class );  
    1146.             boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0;  
    1147.             if ( explicitInheritanceJoinedColumns ) {  
    1148.                 int nbrOfInhJoinedColumns = jcsAnn.value().length;  
    1149.                 PrimaryKeyJoinColumn jcAnn;  
    1150.                 inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns];  
    1151.                 for ( int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++ ) {  
    1152.                     jcAnn = jcsAnn.value()[colIndex];  
    1153.                     inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn(  
    1154.                             jcAnn, null, superEntity.getIdentifier(),  
    1155.                             ( Map<String, Join> ) null, ( PropertyHolder ) null, mappings  
    1156.                     );  
    1157.                 }  
    1158.             }  
    1159.             else {  
    1160.                 PrimaryKeyJoinColumn jcAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class );  
    1161.                 inheritanceJoinedColumns = new Ejb3JoinColumn[1];  
    1162.                 inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn(  
    1163.                         jcAnn, null, superEntity.getIdentifier(),  
    1164.                         ( Map<String, Join> ) null, ( PropertyHolder ) null, mappings  
    1165.                 );  
    1166.             }  
    1167.             log.trace( "Subclass joined column(s) created" );  
    1168.         }  
    1169.         else {  
    1170.             if ( clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumns.class )  
    1171.                     || clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumn.class ) ) {  
    1172.                 log.warn( "Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored" );  
    1173.             }  
    1174.         }  
    1175.         return inheritanceJoinedColumns;  
    1176.     }  
    1177.   
    1178.     private static PersistentClass getSuperEntity(XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, Mappings mappings, InheritanceState inheritanceState) {  
    1179.         InheritanceState superEntityState = InheritanceState.getInheritanceStateOfSuperEntity(  
    1180.                 clazzToProcess, inheritanceStatePerClass  
    1181.         );  
    1182.         PersistentClass superEntity = superEntityState != null ?  
    1183.                 mappings.getClass(  
    1184.                         superEntityState.getClazz().getName()  
    1185.                 ) :  
    1186.                 null;  
    1187.         if ( superEntity == null ) {  
    1188.             //check if superclass is not a potential persistent class  
    1189.             if ( inheritanceState.hasParents() ) {  
    1190.                 throw new AssertionFailure(  
    1191.                         "Subclass has to be binded after it's mother class: "  
    1192.                                 + superEntityState.getClazz().getName()  
    1193.                 );  
    1194.             }  
    1195.         }  
    1196.         return superEntity;  
    1197.     }  
    1198.   
    1199.     private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassType classType) {  
    1200.         if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) //will be processed by their subentities  
    1201.                 || AnnotatedClassType.NONE.equals( classType ) //to be ignored  
    1202.                 || AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration  
    1203.                 ) {  
    1204.             if ( AnnotatedClassType.NONE.equals( classType )  
    1205.                     && clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) {  
    1206.                 log.warn(  
    1207.                         "Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity "  
    1208.                                 + "(most likely a user error): {}", clazzToProcess.getName()  
    1209.                 );  
    1210.             }  
    1211.             return false;  
    1212.         }  
    1213.   
    1214.         if ( !classType.equals( AnnotatedClassType.ENTITY ) ) {  
    1215.             throw new AnnotationException(  
    1216.                     "Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess  
    1217.                             .getName()  
    1218.             );  
    1219.         }  
    1220.   
    1221.         return true;  
    1222.     }  
    1223.   
    1224.     /* 
    1225.      * Process the filters defined on the given class, as well as all filters defined 
    1226.      * on the MappedSuperclass(s) in the inheritance hierarchy 
    1227.      */  
    1228.   
    1229.     private static void bindFilters(XClass annotatedClass, EntityBinder entityBinder,  
    1230.                                     Mappings mappings) {  
    1231.   
    1232.         bindFilters( annotatedClass, entityBinder );  
    1233.   
    1234.         XClass classToProcess = annotatedClass.getSuperclass();  
    1235.         while ( classToProcess != null ) {  
    1236.             AnnotatedClassType classType = mappings.getClassType( classToProcess );  
    1237.             if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) ) {  
    1238.                 bindFilters( classToProcess, entityBinder );  
    1239.             }  
    1240.             classToProcess = classToProcess.getSuperclass();  
    1241.         }  
    1242.   
    1243.     }  
    1244.   
    1245.     private static void bindFilters(XAnnotatedElement annotatedElement, EntityBinder entityBinder) {  
    1246.   
    1247.         Filters filtersAnn = annotatedElement.getAnnotation( Filters.class );  
    1248.         if ( filtersAnn != null ) {  
    1249.             for ( Filter filter : filtersAnn.value() ) {  
    1250.                 entityBinder.addFilter( filter.name(), filter.condition() );  
    1251.             }  
    1252.         }  
    1253.   
    1254.         Filter filterAnn = annotatedElement.getAnnotation( Filter.class );  
    1255.         if ( filterAnn != null ) {  
    1256.             entityBinder.addFilter( filterAnn.name(), filterAnn.condition() );  
    1257.         }  
    1258.     }  
    1259.   
    1260.     private static void bindFilterDefs(XAnnotatedElement annotatedElement, Mappings mappings) {  
    1261.         FilterDef defAnn = annotatedElement.getAnnotation( FilterDef.class );  
    1262.         FilterDefs defsAnn = annotatedElement.getAnnotation( FilterDefs.class );  
    1263.         if ( defAnn != null ) {  
    1264.             bindFilterDef( defAnn, mappings );  
    1265.         }  
    1266.         if ( defsAnn != null ) {  
    1267.             for ( FilterDef def : defsAnn.value() ) {  
    1268.                 bindFilterDef( def, mappings );  
    1269.             }  
    1270.         }  
    1271.     }  
    1272.   
    1273.     private static void bindFilterDef(FilterDef defAnn, Mappings mappings) {  
    1274.         Map<String, org.hibernate.type.Type> params = new HashMap<String, org.hibernate.type.Type>();  
    1275.         for ( ParamDef param : defAnn.parameters() ) {  
    1276.             params.put( param.name(), mappings.getTypeResolver().heuristicType( param.type() ) );  
    1277.         }  
    1278.         FilterDefinition def = new FilterDefinition( defAnn.name(), defAnn.defaultCondition(), params );  
    1279.         log.info( "Binding filter definition: {}", def.getFilterName() );  
    1280.         mappings.addFilterDefinition( def );  
    1281.     }  
    1282.   
    1283.     private static void bindTypeDefs(XAnnotatedElement annotatedElement, Mappings mappings) {  
    1284.         TypeDef defAnn = annotatedElement.getAnnotation( TypeDef.class );  
    1285.         TypeDefs defsAnn = annotatedElement.getAnnotation( TypeDefs.class );  
    1286.         if ( defAnn != null ) {  
    1287.             bindTypeDef( defAnn, mappings );  
    1288.         }  
    1289.         if ( defsAnn != null ) {  
    1290.             for ( TypeDef def : defsAnn.value() ) {  
    1291.                 bindTypeDef( def, mappings );  
    1292.             }  
    1293.         }  
    1294.     }  
    1295.   
    1296.     private static void bindFetchProfiles(XAnnotatedElement annotatedElement, Mappings mappings) {  
    1297.         FetchProfile fetchProfileAnnotation = annotatedElement.getAnnotation( FetchProfile.class );  
    1298.         FetchProfiles fetchProfileAnnotations = annotatedElement.getAnnotation( FetchProfiles.class );  
    1299.         if ( fetchProfileAnnotation != null ) {  
    1300.             bindFetchProfile( fetchProfileAnnotation, mappings );  
    1301.         }  
    1302.         if ( fetchProfileAnnotations != null ) {  
    1303.             for ( FetchProfile profile : fetchProfileAnnotations.value() ) {  
    1304.                 bindFetchProfile( profile, mappings );  
    1305.             }  
    1306.         }  
    1307.     }  
    1308.   
    1309.     private static void bindFetchProfile(FetchProfile fetchProfileAnnotation, Mappings mappings) {  
    1310.         for ( FetchProfile.FetchOverride fetch : fetchProfileAnnotation.fetchOverrides() ) {  
    1311.             org.hibernate.annotations.FetchMode mode = fetch.mode();  
    1312.             if ( !mode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) {  
    1313.                 throw new MappingException( "Only FetchMode.JOIN is currently supported" );  
    1314.             }  
    1315.   
    1316.             SecondPass sp = new VerifyFetchProfileReferenceSecondPass( fetchProfileAnnotation.name(), fetch, mappings );  
    1317.             mappings.addSecondPass( sp );  
    1318.         }  
    1319.     }  
    1320.   
    1321.     private static void bindTypeDef(TypeDef defAnn, Mappings mappings) {  
    1322.         Properties params = new Properties();  
    1323.         for ( Parameter param : defAnn.parameters() ) {  
    1324.             params.setProperty( param.name(), param.value() );  
    1325.         }  
    1326.   
    1327.         if ( BinderHelper.isEmptyAnnotationValue( defAnn.name() ) && defAnn.defaultForType().equals( void.class ) ) {  
    1328.             throw new AnnotationException(  
    1329.                     "Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass " +  
    1330.                             defAnn.typeClass().getName()  
    1331.             );  
    1332.         }  
    1333.   
    1334.         if ( !BinderHelper.isEmptyAnnotationValue( defAnn.name() ) ) {  
    1335.             log.info( "Binding type definition: {}", defAnn.name() );  
    1336.             mappings.addTypeDef( defAnn.name(), defAnn.typeClass().getName(), params );  
    1337.         }  
    1338.         if ( !defAnn.defaultForType().equals( void.class ) ) {  
    1339.             log.info( "Binding type definition: {}", defAnn.defaultForType().getName() );  
    1340.             mappings.addTypeDef( defAnn.defaultForType().getName(), defAnn.typeClass().getName(), params );  
    1341.         }  
    1342.   
    1343.     }  
    1344.   
    1345.   
    1346.     private static void bindDiscriminatorToPersistentClass(  
    1347.             RootClass rootClass,  
    1348.             Ejb3DiscriminatorColumn discriminatorColumn,  
    1349.             Map<String, Join> secondaryTables,  
    1350.             PropertyHolder propertyHolder,  
    1351.             Mappings mappings) {  
    1352.         if ( rootClass.getDiscriminator() == null ) {  
    1353.             if ( discriminatorColumn == null ) {  
    1354.                 throw new AssertionFailure( "discriminator column should have been built" );  
    1355.             }  
    1356.             discriminatorColumn.setJoins( secondaryTables );  
    1357.             discriminatorColumn.setPropertyHolder( propertyHolder );  
    1358.             SimpleValue discrim = new SimpleValue( mappings, rootClass.getTable() );  
    1359.             rootClass.setDiscriminator( discrim );  
    1360.             discriminatorColumn.linkWithValue( discrim );  
    1361.             discrim.setTypeName( discriminatorColumn.getDiscriminatorTypeName() );  
    1362.             rootClass.setPolymorphic( true );  
    1363.             log.trace( "Setting discriminator for entity {}", rootClass.getEntityName() );  
    1364.         }  
    1365.     }  
    1366.   
    1367.     /** 
    1368.      * @param elements List of {@code ProperyData} instances 
    1369.      * @param defaultAccessType The default value access strategy which has to be used in case no explicit local access 
    1370.      * strategy is used 
    1371.      * @param propertyContainer Metadata about a class and its properties 
    1372.      * @param mappings Mapping meta data 
    1373.      * 
    1374.      * @return the number of id properties found while iterating the elements of {@code annotatedClass} using 
    1375.      *         the determined access strategy, {@code false} otherwise. 
    1376.      */  
    1377.     static int addElementsOfClass(  
    1378.             List<PropertyData> elements,  
    1379.             AccessType defaultAccessType,  
    1380.             PropertyContainer propertyContainer,  
    1381.             Mappings mappings) {  
    1382.         int idPropertyCounter = 0;  
    1383.         AccessType accessType = defaultAccessType;  
    1384.   
    1385.         if ( propertyContainer.hasExplicitAccessStrategy() ) {  
    1386.             accessType = propertyContainer.getExplicitAccessStrategy();  
    1387.         }  
    1388.   
    1389.         Collection<XProperty> properties = propertyContainer.getProperties( accessType );  
    1390.         for ( XProperty p : properties ) {  
    1391.             final int currentIdPropertyCounter = addProperty(  
    1392.                     propertyContainer, p, elements, accessType.getType(), mappings  
    1393.             );  
    1394.             idPropertyCounter += currentIdPropertyCounter;  
    1395.         }  
    1396.         return idPropertyCounter;  
    1397.     }  
    1398.   
    1399.     private static int addProperty(  
    1400.             PropertyContainer propertyContainer,  
    1401.             XProperty property,  
    1402.             List<PropertyData> annElts,  
    1403.             String propertyAccessor,  
    1404.             Mappings mappings) {  
    1405.         final XClass declaringClass = propertyContainer.getDeclaringClass();  
    1406.         final XClass entity = propertyContainer.getEntityAtStake();  
    1407.         int idPropertyCounter = 0;  
    1408.         PropertyData propertyAnnotatedElement = new PropertyInferredData(  
    1409.                 declaringClass, property, propertyAccessor,  
    1410.                 mappings.getReflectionManager()  
    1411.         );  
    1412.   
    1413.         /* 
    1414.          * put element annotated by @Id in front 
    1415.          * since it has to be parsed before any association by Hibernate 
    1416.          */  
    1417.         final XAnnotatedElement element = propertyAnnotatedElement.getProperty();  
    1418.         if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {  
    1419.             annElts.add( 0, propertyAnnotatedElement );  
    1420.             /** 
    1421.              * The property must be put in hibernate.properties as it's a system wide property. Fixable? 
    1422.              * TODO support true/false/default on the property instead of present / not present 
    1423.              * TODO is @Column mandatory? 
    1424.              * TODO add method support 
    1425.              */  
    1426.             if ( mappings.isSpecjProprietarySyntaxEnabled() ) {  
    1427.                 if ( element.isAnnotationPresent( Id.class ) && element.isAnnotationPresent( Column.class ) ) {  
    1428.                     String columnName = element.getAnnotation( Column.class ).name();  
    1429.                     for ( XProperty prop : declaringClass.getDeclaredProperties( AccessType.FIELD.getType() ) ) {  
    1430.                         if ( prop.isAnnotationPresent( JoinColumn.class )  
    1431.                                 && prop.getAnnotation( JoinColumn.class ).name().equals( columnName )  
    1432.                                 && !prop.isAnnotationPresent( MapsId.class ) ) {  
    1433.                             //create a PropertyData fpr the specJ property holding the mapping  
    1434.                             PropertyData specJPropertyData = new PropertyInferredData(  
    1435.                                     declaringClass,  //same dec  
    1436.                                     prop, // the actual @XToOne property  
    1437.                                     propertyAccessor, //TODO we should get the right accessor but the same as id would do  
    1438.                                     mappings.getReflectionManager()  
    1439.                             );  
    1440.                             mappings.addPropertyAnnotatedWithMapsIdSpecj( entity, specJPropertyData, element.toString() );  
    1441.                         }  
    1442.                     }  
    1443.                 }  
    1444.             }  
    1445.   
    1446.             if ( element.isAnnotationPresent( ManyToOne.class ) || element.isAnnotationPresent( OneToOne.class ) ) {  
    1447.                 mappings.addToOneAndIdProperty( entity, propertyAnnotatedElement );  
    1448.             }  
    1449.             idPropertyCounter++;  
    1450.         }  
    1451.         else {  
    1452.             annElts.add( propertyAnnotatedElement );  
    1453.         }  
    1454.         if ( element.isAnnotationPresent( MapsId.class ) ) {  
    1455.             mappings.addPropertyAnnotatedWithMapsId( entity, propertyAnnotatedElement );  
    1456.         }  
    1457.   
    1458.         return idPropertyCounter;  
    1459.     }  
    1460.   
    1461.     /* 
    1462.      * Process annotation of a particular property 
    1463.      */  
    1464.   
    1465.     private static void processElementAnnotations(  
    1466.             PropertyHolder propertyHolder,  
    1467.             Nullability nullability,  
    1468.             PropertyData inferredData,  
    1469.             HashMap<String, IdGenerator> classGenerators,  
    1470.             EntityBinder entityBinder,  
    1471.             boolean isIdentifierMapper,  
    1472.             boolean isComponentEmbedded,  
    1473.             boolean inSecondPass,  
    1474.             Mappings mappings,  
    1475.             Map<XClass, InheritanceState> inheritanceStatePerClass) throws MappingException {  
    1476.         /** 
    1477.          * inSecondPass can only be used to apply right away the second pass of a composite-element 
    1478.          * Because it's a value type, there is no bidirectional association, hence second pass 
    1479.          * ordering does not matter 
    1480.          */  
    1481.   
    1482.         log.trace(  
    1483.                 "Processing annotations of {}.{}", propertyHolder.getEntityName(), inferredData.getPropertyName()  
    1484.         );  
    1485.   
    1486.         final XProperty property = inferredData.getProperty();  
    1487.         if ( property.isAnnotationPresent( Parent.class ) ) {  
    1488.             if ( propertyHolder.isComponent() ) {  
    1489.                 propertyHolder.setParentProperty( property.getName() );  
    1490.             }  
    1491.             else {  
    1492.                 throw new AnnotationException(  
    1493.                         "@Parent cannot be applied outside an embeddable object: "  
    1494.                                 + BinderHelper.getPath( propertyHolder, inferredData )  
    1495.                 );  
    1496.             }  
    1497.             return;  
    1498.         }  
    1499.   
    1500.         ColumnsBuilder columnsBuilder = new ColumnsBuilder(  
    1501.                 propertyHolder, nullability, property, inferredData, entityBinder, mappings  
    1502.         ).extractMetadata();  
    1503.         Ejb3Column[] columns = columnsBuilder.getColumns();  
    1504.         Ejb3JoinColumn[] joinColumns = columnsBuilder.getJoinColumns();  
    1505.           
    1506.           
    1507.         final XClass returnedClass = inferredData.getClassOrElement();  
    1508.   
    1509.         //prepare PropertyBinder  
    1510.         PropertyBinder propertyBinder = new PropertyBinder();  
    1511.         propertyBinder.setName( inferredData.getPropertyName() );  
    1512.         propertyBinder.setReturnedClassName( inferredData.getTypeName() );  
    1513.         propertyBinder.setAccessType( inferredData.getDefaultAccess() );  
    1514.         propertyBinder.setHolder( propertyHolder );  
    1515.         propertyBinder.setProperty( property );  
    1516.         propertyBinder.setReturnedClass( inferredData.getPropertyClass() );  
    1517.         propertyBinder.setMappings( mappings );  
    1518.         if ( isIdentifierMapper ) {  
    1519.             propertyBinder.setInsertable( false );  
    1520.             propertyBinder.setUpdatable( false );  
    1521.         }  
    1522.         propertyBinder.setDeclaringClass( inferredData.getDeclaringClass() );  
    1523.         propertyBinder.setEntityBinder( entityBinder );  
    1524.         propertyBinder.setInheritanceStatePerClass( inheritanceStatePerClass );  
    1525.   
    1526.         boolean isId = !entityBinder.isIgnoreIdAnnotations() &&  
    1527.                 ( property.isAnnotationPresent( Id.class )  
    1528.                         || property.isAnnotationPresent( EmbeddedId.class ) );  
    1529.         propertyBinder.setId( isId );  
    1530.   
    1531.         if ( property.isAnnotationPresent( Version.class ) ) {  
    1532.             if ( isIdentifierMapper ) {  
    1533.                 throw new AnnotationException(  
    1534.                         "@IdClass class should not have @Version property"  
    1535.                 );  
    1536.             }  
    1537.             if ( !( propertyHolder.getPersistentClass() instanceof RootClass ) ) {  
    1538.                 throw new AnnotationException(  
    1539.                         "Unable to define/override @Version on a subclass: "  
    1540.                                 + propertyHolder.getEntityName()  
    1541.                 );  
    1542.             }  
    1543.             if ( !propertyHolder.isEntity() ) {  
    1544.                 throw new AnnotationException(  
    1545.                         "Unable to define @Version on an embedded class: "  
    1546.                                 + propertyHolder.getEntityName()  
    1547.                 );  
    1548.             }  
    1549.             log.trace( "{} is a version property", inferredData.getPropertyName() );  
    1550.             RootClass rootClass = ( RootClass ) propertyHolder.getPersistentClass();  
    1551.             propertyBinder.setColumns( columns );  
    1552.             Property prop = propertyBinder.makePropertyValueAndBind();  
    1553.             setVersionInformation( property, propertyBinder );  
    1554.             rootClass.setVersion( prop );  
    1555.   
    1556.             //If version is on a mapped superclass, update the mapping  
    1557.             final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(  
    1558.                     inferredData.getDeclaringClass(),  
    1559.                     inheritanceStatePerClass,  
    1560.                     mappings  
    1561.             );  
    1562.             if ( superclass != null ) {  
    1563.                 superclass.setDeclaredVersion( prop );  
    1564.             }  
    1565.             else {  
    1566.                 //we know the property is on the actual entity  
    1567.                 rootClass.setDeclaredVersion( prop );  
    1568.             }  
    1569.   
    1570.             SimpleValue simpleValue = ( SimpleValue ) prop.getValue();  
    1571.             simpleValue.setNullValue( "undefined" );  
    1572.             rootClass.setOptimisticLockMode( Versioning.OPTIMISTIC_LOCK_VERSION );  
    1573.             log.trace(  
    1574.                     "Version name: {}, unsavedValue: {}", rootClass.getVersion().getName(),  
    1575.                     ( ( SimpleValue ) rootClass.getVersion().getValue() ).getNullValue()  
    1576.             );  
    1577.         }  
    1578.         else {  
    1579.             final boolean forcePersist = property.isAnnotationPresent( MapsId.class )  
    1580.                     || property.isAnnotationPresent( Id.class );  
    1581.             if ( property.isAnnotationPresent( ManyToOne.class ) ) {  
    1582.                 ManyToOne ann = property.getAnnotation( ManyToOne.class );  
    1583.   
    1584.                 //check validity  
    1585.                 if ( property.isAnnotationPresent( Column.class )  
    1586.                         || property.isAnnotationPresent( Columns.class ) ) {  
    1587.                     throw new AnnotationException(  
    1588.                             "@Column(s) not allowed on a @ManyToOne property: "  
    1589.                                     + BinderHelper.getPath( propertyHolder, inferredData )  
    1590.                     );  
    1591.                 }  
    1592.   
    1593.                 Cascade hibernateCascade = property.getAnnotation( Cascade.class );  
    1594.                 NotFound notFound = property.getAnnotation( NotFound.class );  
    1595.                 boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );  
    1596.                 OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );  
    1597.                 boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );  
    1598.                 JoinTable assocTable = propertyHolder.getJoinTable( property );  
    1599.                 if ( assocTable != null ) {  
    1600.                     Join join = propertyHolder.addJoin( assocTable, false );  
    1601.                     for ( Ejb3JoinColumn joinColumn : joinColumns ) {  
    1602.                         joinColumn.setSecondaryTableName( join.getTable().getName() );  
    1603.                     }  
    1604.                 }  
    1605.                 final boolean mandatory = !ann.optional() || forcePersist;  
    1606.                 bindManyToOne(  
    1607.                         getCascadeStrategy( ann.cascade(), hibernateCascade, false, forcePersist ),  
    1608.                         joinColumns,  
    1609.                         !mandatory,  
    1610.                         ignoreNotFound, onDeleteCascade,  
    1611.                         ToOneBinder.getTargetEntity( inferredData, mappings ),  
    1612.                         propertyHolder,  
    1613.                         inferredData, false, isIdentifierMapper,  
    1614.                         inSecondPass, propertyBinder, mappings  
    1615.                 );  
    1616.             }  
    1617.             else if ( property.isAnnotationPresent( OneToOne.class ) ) {  
    1618.                 OneToOne ann = property.getAnnotation( OneToOne.class );  
    1619.   
    1620.                 //check validity  
    1621.                 if ( property.isAnnotationPresent( Column.class )  
    1622.                         || property.isAnnotationPresent( Columns.class ) ) {  
    1623.                     throw new AnnotationException(  
    1624.                             "@Column(s) not allowed on a @OneToOne property: "  
    1625.                                     + BinderHelper.getPath( propertyHolder, inferredData )  
    1626.                     );  
    1627.                 }  
    1628.   
    1629.                 //FIXME support a proper PKJCs  
    1630.                 boolean trueOneToOne = property.isAnnotationPresent( PrimaryKeyJoinColumn.class )  
    1631.                         || property.isAnnotationPresent( PrimaryKeyJoinColumns.class );  
    1632.                 Cascade hibernateCascade = property.getAnnotation( Cascade.class );  
    1633.                 NotFound notFound = property.getAnnotation( NotFound.class );  
    1634.                 boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );  
    1635.                 OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );  
    1636.                 boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );  
    1637.                 JoinTable assocTable = propertyHolder.getJoinTable( property );  
    1638.                 if ( assocTable != null ) {  
    1639.                     Join join = propertyHolder.addJoin( assocTable, false );  
    1640.                     for ( Ejb3JoinColumn joinColumn : joinColumns ) {  
    1641.                         joinColumn.setSecondaryTableName( join.getTable().getName() );  
    1642.                     }  
    1643.                 }  
    1644.                 //MapsId means the columns belong to the pk => not null  
    1645.                 //@PKJC must be constrained  
    1646.                 final boolean mandatory = !ann.optional() || forcePersist || trueOneToOne;  
    1647.                 bindOneToOne(  
    1648.                         getCascadeStrategy( ann.cascade(), hibernateCascade, ann.orphanRemoval(), forcePersist ),  
    1649.                         joinColumns,  
    1650.                         !mandatory,  
    1651.                         getFetchMode( ann.fetch() ),  
    1652.                         ignoreNotFound, onDeleteCascade,  
    1653.                         ToOneBinder.getTargetEntity( inferredData, mappings ),  
    1654.                         propertyHolder,  
    1655.                         inferredData,  
    1656.                         ann.mappedBy(),  
    1657.                         trueOneToOne,  
    1658.                         isIdentifierMapper,  
    1659.                         inSecondPass,  
    1660.                         propertyBinder,  
    1661.                         mappings  
    1662.                 );  
    1663.             }  
    1664.             else if ( property.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {  
    1665.   
    1666.                 //check validity  
    1667.                 if ( property.isAnnotationPresent( Column.class )  
    1668.                         || property.isAnnotationPresent( Columns.class ) ) {  
    1669.                     throw new AnnotationException(  
    1670.                             "@Column(s) not allowed on a @Any property: "  
    1671.                                     + BinderHelper.getPath( propertyHolder, inferredData )  
    1672.                     );  
    1673.                 }  
    1674.   
    1675.                 Cascade hibernateCascade = property.getAnnotation( Cascade.class );  
    1676.                 OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );  
    1677.                 boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );  
    1678.                 JoinTable assocTable = propertyHolder.getJoinTable( property );  
    1679.                 if ( assocTable != null ) {  
    1680.                     Join join = propertyHolder.addJoin( assocTable, false );  
    1681.                     for ( Ejb3JoinColumn joinColumn : joinColumns ) {  
    1682.                         joinColumn.setSecondaryTableName( join.getTable().getName() );  
    1683.                     }  
    1684.                 }  
    1685.                 bindAny(  
    1686.                         getCascadeStrategy( null, hibernateCascade, false, forcePersist ),  
    1687.                         //@Any has not cascade attribute  
    1688.                         joinColumns,  
    1689.                         onDeleteCascade,  
    1690.                         nullability,  
    1691.                         propertyHolder,  
    1692.                         inferredData,  
    1693.                         entityBinder,  
    1694.                         isIdentifierMapper,  
    1695.                         mappings  
    1696.                 );  
    1697.             }  
    1698.             else if ( property.isAnnotationPresent( OneToMany.class )  
    1699.                     || property.isAnnotationPresent( ManyToMany.class )  
    1700.                     || property.isAnnotationPresent( CollectionOfElements.class ) //legacy Hibernate  
    1701.                     || property.isAnnotationPresent( ElementCollection.class )  
    1702.                     || property.isAnnotationPresent( ManyToAny.class ) ) {  
    1703.                 OneToMany oneToManyAnn = property.getAnnotation( OneToMany.class );  
    1704.                 ManyToMany manyToManyAnn = property.getAnnotation( ManyToMany.class );  
    1705.                 ElementCollection elementCollectionAnn = property.getAnnotation( ElementCollection.class );  
    1706.                 CollectionOfElements collectionOfElementsAnn = property.getAnnotation( CollectionOfElements.class ); //legacy hibernate  
    1707.   
    1708.                 final IndexColumn indexColumn;  
    1709.   
    1710.                 if ( property.isAnnotationPresent( OrderColumn.class ) ) {  
    1711.                     indexColumn = IndexColumn.buildColumnFromAnnotation(  
    1712.                             property.getAnnotation( OrderColumn.class ),  
    1713.                             propertyHolder,  
    1714.                             inferredData,  
    1715.                             entityBinder.getSecondaryTables(),  
    1716.                             mappings  
    1717.                     );  
    1718.                 }  
    1719.                 else {  
    1720.                     //if @IndexColumn is not there, the generated IndexColumn is an implicit column and not used.  
    1721.                     //so we can leave the legacy processing as the default  
    1722.                     indexColumn = IndexColumn.buildColumnFromAnnotation(  
    1723.                             property.getAnnotation( org.hibernate.annotations.IndexColumn.class ),  
    1724.                             propertyHolder,  
    1725.                             inferredData,  
    1726.                             mappings  
    1727.                     );  
    1728.                 }  
    1729.                 CollectionBinder collectionBinder = CollectionBinder.getCollectionBinder(  
    1730.                         propertyHolder.getEntityName(),  
    1731.                         property,  
    1732.                         !indexColumn.isImplicit(),  
    1733.                         property.isAnnotationPresent( CollectionOfElements.class )  
    1734.                                 || property.isAnnotationPresent( org.hibernate.annotations.MapKey.class )  
    1735.                                 || property.isAnnotationPresent( MapKeyType.class )  
    1736.   
    1737.                         // || property.isAnnotationPresent( ManyToAny.class )  
    1738.                 );  
    1739.                 collectionBinder.setIndexColumn( indexColumn );  
    1740.                 collectionBinder.setMapKey( property.getAnnotation( MapKey.class ) );  
    1741.                 collectionBinder.setPropertyName( inferredData.getPropertyName() );  
    1742.                 BatchSize batchAnn = property.getAnnotation( BatchSize.class );  
    1743.                 collectionBinder.setBatchSize( batchAnn );  
    1744.                 javax.persistence.OrderBy ejb3OrderByAnn = property.getAnnotation( javax.persistence.OrderBy.class );  
    1745.                 OrderBy orderByAnn = property.getAnnotation( OrderBy.class );  
    1746.                 collectionBinder.setEjb3OrderBy( ejb3OrderByAnn );  
    1747.                 collectionBinder.setSqlOrderBy( orderByAnn );  
    1748.                 Sort sortAnn = property.getAnnotation( Sort.class );  
    1749.                 collectionBinder.setSort( sortAnn );  
    1750.                 Cache cachAnn = property.getAnnotation( Cache.class );  
    1751.                 collectionBinder.setCache( cachAnn );  
    1752.                 collectionBinder.setPropertyHolder( propertyHolder );  
    1753.                 Cascade hibernateCascade = property.getAnnotation( Cascade.class );  
    1754.                 NotFound notFound = property.getAnnotation( NotFound.class );  
    1755.                 boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );  
    1756.                 collectionBinder.setIgnoreNotFound( ignoreNotFound );  
    1757.                 collectionBinder.setCollectionType( inferredData.getProperty().getElementClass() );  
    1758.                 collectionBinder.setMappings( mappings );  
    1759.                 collectionBinder.setAccessType( inferredData.getDefaultAccess() );  
    1760.   
    1761.                 Ejb3Column[] elementColumns;  
    1762.                 //do not use "element" if you are a JPA 2 @ElementCollection only for legacy Hibernate mappings  
    1763.                 boolean isJPA2ForValueMapping = property.isAnnotationPresent( ElementCollection.class );  
    1764.                 PropertyData virtualProperty = isJPA2ForValueMapping ? inferredData : new WrappedInferredData(  
    1765.                         inferredData, "element"  
    1766.                 );  
    1767.                 if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent(  
    1768.                         Formula.class  
    1769.                 ) ) {  
    1770.                     Column ann = property.getAnnotation( Column.class );  
    1771.                     Formula formulaAnn = property.getAnnotation( Formula.class );  
    1772.                     elementColumns = Ejb3Column.buildColumnFromAnnotation(  
    1773.                             new Column[] { ann },  
    1774.                             formulaAnn,  
    1775.                             nullability,  
    1776.                             propertyHolder,  
    1777.                             virtualProperty,  
    1778.                             entityBinder.getSecondaryTables(),  
    1779.                             mappings  
    1780.                     );  
    1781.                 }  
    1782.                 else if ( property.isAnnotationPresent( Columns.class ) ) {  
    1783.                     Columns anns = property.getAnnotation( Columns.class );  
    1784.                     elementColumns = Ejb3Column.buildColumnFromAnnotation(  
    1785.                             anns.columns(), null, nullability, propertyHolder, virtualProperty,  
    1786.                             entityBinder.getSecondaryTables(), mappings  
    1787.                     );  
    1788.                 }  
    1789.                 else {  
    1790.                     elementColumns = Ejb3Column.buildColumnFromAnnotation(  
    1791.                             null,  
    1792.                             null,  
    1793.                             nullability,  
    1794.                             propertyHolder,  
    1795.                             virtualProperty,  
    1796.                             entityBinder.getSecondaryTables(),  
    1797.                             mappings  
    1798.                     );  
    1799.                 }  
    1800.                 {  
    1801.                     Column[] keyColumns = null;  
    1802.                     //JPA 2 has priority and has different default column values, differenciate legacy from JPA 2  
    1803.                     Boolean isJPA2 = null;  
    1804.                     if ( property.isAnnotationPresent( MapKeyColumn.class ) ) {  
    1805.                         isJPA2 = Boolean.TRUE;  
    1806.                         keyColumns = new Column[] { new MapKeyColumnDelegator( property.getAnnotation( MapKeyColumn.class ) ) };  
    1807.                     }  
    1808.                     else if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) ) {  
    1809.                         if ( isJPA2 == null ) {  
    1810.                             isJPA2 = Boolean.FALSE;  
    1811.                         }  
    1812.                         keyColumns = property.getAnnotation( org.hibernate.annotations.MapKey.class ).columns();  
    1813.                     }  
    1814.   
    1815.                     //not explicitly legacy  
    1816.                     if ( isJPA2 == null ) {  
    1817.                         isJPA2 = Boolean.TRUE;  
    1818.                     }  
    1819.   
    1820.                     //nullify empty array  
    1821.                     keyColumns = keyColumns != null && keyColumns.length > 0 ? keyColumns : null;  
    1822.   
    1823.                     //"mapkey" is the legacy column name of the key column pre JPA 2  
    1824.                     PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" );  
    1825.                     Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation(  
    1826.                             keyColumns,  
    1827.                             null,  
    1828.                             Nullability.FORCED_NOT_NULL,  
    1829.                             propertyHolder,  
    1830.                             isJPA2 ? inferredData : mapKeyVirtualProperty,  
    1831.                             isJPA2 ? "_KEY" : null,  
    1832.                             entityBinder.getSecondaryTables(),  
    1833.                             mappings  
    1834.                     );  
    1835.                     collectionBinder.setMapKeyColumns( mapColumns );  
    1836.                 }  
    1837.                 {  
    1838.                     JoinColumn[] joinKeyColumns = null;  
    1839.                     //JPA 2 has priority and has different default column values, differenciate legacy from JPA 2  
    1840.                     Boolean isJPA2 = null;  
    1841.                     if ( property.isAnnotationPresent( MapKeyJoinColumns.class ) ) {  
    1842.                         isJPA2 = Boolean.TRUE;  
    1843.                         final MapKeyJoinColumn[] mapKeyJoinColumns = property.getAnnotation( MapKeyJoinColumns.class )  
    1844.                                 .value();  
    1845.                         joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];  
    1846.                         int index = 0;  
    1847.                         for ( MapKeyJoinColumn joinColumn : mapKeyJoinColumns ) {  
    1848.                             joinKeyColumns[index] = new MapKeyJoinColumnDelegator( joinColumn );  
    1849.                             index++;  
    1850.                         }  
    1851.                         if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {  
    1852.                             throw new AnnotationException(  
    1853.                                     "@MapKeyJoinColumn and @MapKeyJoinColumns used on the same property: "  
    1854.                                             + BinderHelper.getPath( propertyHolder, inferredData )  
    1855.                             );  
    1856.                         }  
    1857.                     }  
    1858.                     else if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {  
    1859.                         isJPA2 = Boolean.TRUE;  
    1860.                         joinKeyColumns = new JoinColumn[] {  
    1861.                                 new MapKeyJoinColumnDelegator(  
    1862.                                         property.getAnnotation(  
    1863.                                                 MapKeyJoinColumn.class  
    1864.                                         )  
    1865.                                 )  
    1866.                         };  
    1867.                     }  
    1868.                     else if ( property.isAnnotationPresent( org.hibernate.annotations.MapKeyManyToMany.class ) ) {  
    1869.                         if ( isJPA2 == null ) {  
    1870.                             isJPA2 = Boolean.FALSE;  
    1871.                         }  
    1872.                         joinKeyColumns = property.getAnnotation( org.hibernate.annotations.MapKeyManyToMany.class )  
    1873.                                 .joinColumns();  
    1874.                     }  
    1875.   
    1876.                     //not explicitly legacy  
    1877.                     if ( isJPA2 == null ) {  
    1878.                         isJPA2 = Boolean.TRUE;  
    1879.                     }  
    1880.   
    1881.                     PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" );  
    1882.                     Ejb3JoinColumn[] mapJoinColumns = Ejb3JoinColumn.buildJoinColumnsWithDefaultColumnSuffix(  
    1883.                             joinKeyColumns,  
    1884.                             null,  
    1885.                             entityBinder.getSecondaryTables(),  
    1886.                             propertyHolder,  
    1887.                             isJPA2 ? inferredData.getPropertyName() : mapKeyVirtualProperty.getPropertyName(),  
    1888.                             isJPA2 ? "_KEY" : null,  
    1889.                             mappings  
    1890.                     );  
    1891.                     collectionBinder.setMapKeyManyToManyColumns( mapJoinColumns );  
    1892.                 }  
    1893.   
    1894.                 //potential element  
    1895.                 collectionBinder.setEmbedded( property.isAnnotationPresent( Embedded.class ) );  
    1896.                 collectionBinder.setElementColumns( elementColumns );  
    1897.                 collectionBinder.setProperty( property );  
    1898.   
    1899.                 //TODO enhance exception with @ManyToAny and @CollectionOfElements  
    1900.                 if ( oneToManyAnn != null && manyToManyAnn != null ) {  
    1901.                     throw new AnnotationException(  
    1902.                             "@OneToMany and @ManyToMany on the same property is not allowed: "  
    1903.                                     + propertyHolder.getEntityName() + "." + inferredData.getPropertyName()  
    1904.                     );  
    1905.                 }  
    1906.                 String mappedBy = null;  
    1907.                 if ( oneToManyAnn != null ) {  
    1908.                     for ( Ejb3JoinColumn column : joinColumns ) {  
    1909.                         if ( column.isSecondary() ) {  
    1910.                             throw new NotYetImplementedException( "Collections having FK in secondary table" );  
    1911.                         }  
    1912.                     }  
    1913.                     collectionBinder.setFkJoinColumns( joinColumns );  
    1914.                     mappedBy = oneToManyAnn.mappedBy();  
    1915.                     collectionBinder.setTargetEntity(  
    1916.                             mappings.getReflectionManager().toXClass( oneToManyAnn.targetEntity() )  
    1917.                     );  
    1918.                     collectionBinder.setCascadeStrategy(  
    1919.                             getCascadeStrategy(  
    1920.                                     oneToManyAnn.cascade(), hibernateCascade, oneToManyAnn.orphanRemoval(), false  
    1921.                             )  
    1922.                     );  
    1923.                     collectionBinder.setOneToMany( true );  
    1924.                 }  
    1925.                 else if ( elementCollectionAnn != null  
    1926.                         || collectionOfElementsAnn != null //Hibernate legacy  
    1927.                         ) {  
    1928.                     for ( Ejb3JoinColumn column : joinColumns ) {  
    1929.                         if ( column.isSecondary() ) {  
    1930.                             throw new NotYetImplementedException( "Collections having FK in secondary table" );  
    1931.                         }  
    1932.                     }  
    1933.                     collectionBinder.setFkJoinColumns( joinColumns );  
    1934.                     mappedBy = "";  
    1935.                     final Class<?> targetElement = elementCollectionAnn != null ?  
    1936.                             elementCollectionAnn.targetClass() :  
    1937.                             collectionOfElementsAnn.targetElement();  
    1938.                     collectionBinder.setTargetEntity(  
    1939.                             mappings.getReflectionManager().toXClass( targetElement )  
    1940.                     );  
    1941.                     //collectionBinder.setCascadeStrategy( getCascadeStrategy( embeddedCollectionAnn.cascade(), hibernateCascade ) );  
    1942.                     collectionBinder.setOneToMany( true );  
    1943.                 }  
    1944.                 else if ( manyToManyAnn != null ) {  
    1945.                     mappedBy = manyToManyAnn.mappedBy();  
    1946.                     collectionBinder.setTargetEntity(  
    1947.                             mappings.getReflectionManager().toXClass( manyToManyAnn.targetEntity() )  
    1948.                     );  
    1949.                     collectionBinder.setCascadeStrategy(  
    1950.                             getCascadeStrategy(  
    1951.                                     manyToManyAnn.cascade(), hibernateCascade, false, false  
    1952.                             )  
    1953.                     );  
    1954.                     collectionBinder.setOneToMany( false );  
    1955.                 }  
    1956.                 else if ( property.isAnnotationPresent( ManyToAny.class ) ) {  
    1957.                     mappedBy = "";  
    1958.                     collectionBinder.setTargetEntity(  
    1959.                             mappings.getReflectionManager().toXClass( void.class )  
    1960.                     );  
    1961.                     collectionBinder.setCascadeStrategy( getCascadeStrategy( null, hibernateCascade, false, false ) );  
    1962.                     collectionBinder.setOneToMany( false );  
    1963.                 }  
    1964.                 collectionBinder.setMappedBy( mappedBy );  
    1965.   
    1966.                 bindJoinedTableAssociation(  
    1967.                         property, mappings, entityBinder, collectionBinder, propertyHolder, inferredData, mappedBy  
    1968.                 );  
    1969.   
    1970.                 OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );  
    1971.                 boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );  
    1972.                 collectionBinder.setCascadeDeleteEnabled( onDeleteCascade );  
    1973.                 if ( isIdentifierMapper ) {  
    1974.                     collectionBinder.setInsertable( false );  
    1975.                     collectionBinder.setUpdatable( false );  
    1976.                 }  
    1977.                 if ( property.isAnnotationPresent( CollectionId.class ) ) { //do not compute the generators unless necessary  
    1978.                     HashMap<String, IdGenerator> localGenerators = ( HashMap<String, IdGenerator> ) classGenerators.clone();  
    1979.                     localGenerators.putAll( buildLocalGenerators( property, mappings ) );  
    1980.                     collectionBinder.setLocalGenerators( localGenerators );  
    1981.                 }  
    1982.                 collectionBinder.setInheritanceStatePerClass( inheritanceStatePerClass );  
    1983.                 collectionBinder.setDeclaringClass( inferredData.getDeclaringClass() );  
    1984.                 collectionBinder.bind();  
    1985.   
    1986.             }  
    1987.             //Either a regular property or a basic @Id or @EmbeddedId while not ignoring id annotations  
    1988.             else if ( !isId || !entityBinder.isIgnoreIdAnnotations() ) {  
    1989.                 //define whether the type is a component or not  
    1990.   
    1991.                 boolean isComponent = false;  
    1992.   
    1993.                 //Overrides from @MapsId if needed  
    1994.                 boolean isOverridden = false;  
    1995.                 if ( isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {  
    1996.                     //the associated entity could be using an @IdClass making the overridden property a component  
    1997.                     final PropertyData overridingProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(  
    1998.                             isId, propertyHolder, property.getName(), mappings  
    1999.                     );  
    2000.                     if ( overridingProperty != null ) {  
    2001.                         isOverridden = true;  
    2002.                         final InheritanceState state = inheritanceStatePerClass.get( overridingProperty.getClassOrElement() );  
    2003.                         if ( state != null ) {  
    2004.                             isComponent = isComponent || state.hasIdClassOrEmbeddedId();  
    2005.                         }  
    2006.                         //Get the new column  
    2007.                         columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty( isId );  
    2008.                     }  
    2009.                 }  
    2010.   
    2011.                 isComponent = isComponent  
    2012.                         || property.isAnnotationPresent( Embedded.class )  
    2013.                         || property.isAnnotationPresent( EmbeddedId.class )  
    2014.                         || returnedClass.isAnnotationPresent( Embeddable.class );  
    2015.   
    2016.   
    2017.                 if ( isComponent ) {  
    2018.                     String referencedEntityName = null;  
    2019.                     if ( isOverridden ) {  
    2020.                         final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(  
    2021.                                 isId, propertyHolder, property.getName(), mappings  
    2022.                         );  
    2023.                         referencedEntityName = mapsIdProperty.getClassOrElementName();  
    2024.                     }  
    2025.                     AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );  
    2026.                     propertyBinder = bindComponent(  
    2027.                             inferredData,  
    2028.                             propertyHolder,  
    2029.                             propertyAccessor,  
    2030.                             entityBinder,  
    2031.                             isIdentifierMapper,  
    2032.                             mappings,  
    2033.                             isComponentEmbedded,  
    2034.                             isId,  
    2035.                             inheritanceStatePerClass,  
    2036.                             referencedEntityName,  
    2037.                             isOverridden ? ( Ejb3JoinColumn[] ) columns : null  
    2038.                     );  
    2039.                 }  
    2040.                 else {  
    2041.                     //provide the basic property mapping  
    2042.                     boolean optional = true;  
    2043.                     boolean lazy = false;  
    2044.                     if ( property.isAnnotationPresent( Basic.class ) ) {  
    2045.                         Basic ann = property.getAnnotation( Basic.class );  
    2046.                         optional = ann.optional();  
    2047.                         lazy = ann.fetch() == FetchType.LAZY;  
    2048.                     }  
    2049.                     //implicit type will check basic types and Serializable classes  
    2050.                     if ( isId || ( !optional && nullability != Nullability.FORCED_NULL ) ) {  
    2051.                         //force columns to not null  
    2052.                         for ( Ejb3Column col : columns ) {  
    2053.                             col.forceNotNull();  
    2054.                         }  
    2055.                     }  
    2056.   
    2057.                     propertyBinder.setLazy( lazy );  
    2058.                     propertyBinder.setColumns( columns );  
    2059.                     if ( isOverridden ) {  
    2060.                         final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(  
    2061.                                 isId, propertyHolder, property.getName(), mappings  
    2062.                         );  
    2063.                         propertyBinder.setReferencedEntityName( mapsIdProperty.getClassOrElementName() );  
    2064.                     }  
    2065.   
    2066.                     propertyBinder.makePropertyValueAndBind();  
    2067.   
    2068.                 }  
    2069.                 if ( isOverridden ) {  
    2070.                     final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(  
    2071.                             isId, propertyHolder, property.getName(), mappings  
    2072.                     );  
    2073.                     Map<String, IdGenerator> localGenerators = ( HashMap<String, IdGenerator> ) classGenerators.clone();  
    2074.                     final IdGenerator foreignGenerator = new IdGenerator();  
    2075.                     foreignGenerator.setIdentifierGeneratorStrategy( "assigned" );  
    2076.                     foreignGenerator.setName( "Hibernate-local--foreign generator" );  
    2077.                     foreignGenerator.setIdentifierGeneratorStrategy( "foreign" );  
    2078.                     foreignGenerator.addParam( "property", mapsIdProperty.getPropertyName() );  
    2079.                     localGenerators.put( foreignGenerator.getName(), foreignGenerator );  
    2080.   
    2081.                     BinderHelper.makeIdGenerator(  
    2082.                             ( SimpleValue ) propertyBinder.getValue(),  
    2083.                             foreignGenerator.getIdentifierGeneratorStrategy(),  
    2084.                             foreignGenerator.getName(),  
    2085.                             mappings,  
    2086.                             localGenerators  
    2087.                     );  
    2088.                 }  
    2089.                 if ( isId ) {  
    2090.                     //components and regular basic types create SimpleValue objects  
    2091.                     final SimpleValue value = ( SimpleValue ) propertyBinder.getValue();  
    2092.                     if ( !isOverridden ) {  
    2093.                         processId(  
    2094.                                 propertyHolder,  
    2095.                                 inferredData,  
    2096.                                 value,  
    2097.                                 classGenerators,  
    2098.                                 isIdentifierMapper,  
    2099.                                 mappings  
    2100.                         );  
    2101.                     }  
    2102.                 }  
    2103.             }  
    2104.         }  
    2105.         //init index  
    2106.         //process indexes after everything: in second pass, many to one has to be done before indexes  
    2107.         Index index = property.getAnnotation( Index.class );  
    2108.         if ( index != null ) {  
    2109.             if ( joinColumns != null ) {  
    2110.   
    2111.                 for ( Ejb3Column column : joinColumns ) {  
    2112.                     column.addIndex( index, inSecondPass );  
    2113.                 }  
    2114.             }  
    2115.             else {  
    2116.                 if ( columns != null ) {  
    2117.                     for ( Ejb3Column column : columns ) {  
    2118.                         column.addIndex( index, inSecondPass );  
    2119.                     }  
    2120.                 }  
    2121.             }  
    2122.         }  
    2123.   
    2124.         NaturalId naturalIdAnn = property.getAnnotation( NaturalId.class );  
    2125.         if ( naturalIdAnn != null ) {  
    2126.             if ( joinColumns != null ) {  
    2127.                 for ( Ejb3Column column : joinColumns ) {  
    2128.                     column.addUniqueKey( "_UniqueKey", inSecondPass );  
    2129.                 }  
    2130.             }  
    2131.             else {  
    2132.                 for ( Ejb3Column column : columns ) {  
    2133.                     column.addUniqueKey( "_UniqueKey", inSecondPass );  
    2134.                 }  
    2135.             }  
    2136.         }  
    2137.           
    2138.         //添加自定义注释的处理  
    2139.         CommentBinder.bindColumnComment(property, columns);  
    2140.         //CommentBinder.bindTableComment(clazzToProcess, persistentClass);  
    2141.         //CommentBinder.bindColumnComment(property, column);  
    2142.     }  
    2143.   
    2144.     private static void setVersionInformation(XProperty property, PropertyBinder propertyBinder) {  
    2145.         propertyBinder.getSimpleValueBinder().setVersion( true );         
    2146.         if(property.isAnnotationPresent( Source.class )) {  
    2147.             Source source = property.getAnnotation( Source.class );  
    2148.             propertyBinder.getSimpleValueBinder().setTimestampVersionType( source.value().typeName() );  
    2149.         }  
    2150.     }  
    2151.   
    2152.     private static void processId(  
    2153.             PropertyHolder propertyHolder,  
    2154.             PropertyData inferredData,  
    2155.             SimpleValue idValue,  
    2156.             HashMap<String, IdGenerator> classGenerators,  
    2157.             boolean isIdentifierMapper,  
    2158.             Mappings mappings) {  
    2159.         if ( isIdentifierMapper ) {  
    2160.             throw new AnnotationException(  
    2161.                     "@IdClass class should not have @Id nor @EmbeddedId properties: "  
    2162.                             + BinderHelper.getPath( propertyHolder, inferredData )  
    2163.             );  
    2164.         }  
    2165.         XClass returnedClass = inferredData.getClassOrElement();  
    2166.         XProperty property = inferredData.getProperty();  
    2167.         //clone classGenerator and override with local values  
    2168.         HashMap<String, IdGenerator> localGenerators = ( HashMap<String, IdGenerator> ) classGenerators.clone();  
    2169.         localGenerators.putAll( buildLocalGenerators( property, mappings ) );  
    2170.   
    2171.         //manage composite related metadata  
    2172.         //guess if its a component and find id data access (property, field etc)  
    2173.         final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class )  
    2174.                 || property.isAnnotationPresent( EmbeddedId.class );  
    2175.   
    2176.         GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );  
    2177.         String generatorType = generatedValue != null ?  
    2178.                 generatorType( generatedValue.strategy(), mappings ) :  
    2179.                 "assigned";  
    2180.         String generatorName = generatedValue != null ?  
    2181.                 generatedValue.generator() :  
    2182.                 BinderHelper.ANNOTATION_STRING_DEFAULT;  
    2183.         if ( isComponent ) {  
    2184.             generatorType = "assigned";  
    2185.         } //a component must not have any generator  
    2186.         BinderHelper.makeIdGenerator( idValue, generatorType, generatorName, mappings, localGenerators );  
    2187.   
    2188.         log.trace(  
    2189.                 "Bind {} on {}", ( isComponent ? "@EmbeddedId" : "@Id" ), inferredData.getPropertyName()  
    2190.         );  
    2191.     }  
    2192.   
    2193.     //TODO move that to collection binder?  
    2194.   
    2195.     private static void bindJoinedTableAssociation(  
    2196.             XProperty property,  
    2197.             Mappings mappings,  
    2198.             EntityBinder entityBinder,  
    2199.             CollectionBinder collectionBinder,  
    2200.             PropertyHolder propertyHolder,  
    2201.             PropertyData inferredData,  
    2202.             String mappedBy) {  
    2203.         TableBinder associationTableBinder = new TableBinder();  
    2204.         JoinColumn[] annJoins;  
    2205.         JoinColumn[] annInverseJoins;  
    2206.         JoinTable assocTable = propertyHolder.getJoinTable( property );  
    2207.         CollectionTable collectionTable = property.getAnnotation( CollectionTable.class );  
    2208.   
    2209.         if ( assocTable != null || collectionTable != null ) {  
    2210.   
    2211.             final String catalog;  
    2212.             final String schema;  
    2213.             final String tableName;  
    2214.             final UniqueConstraint[] uniqueConstraints;  
    2215.             final JoinColumn[] joins;  
    2216.             final JoinColumn[] inverseJoins;  
    2217.   
    2218.             //JPA 2 has priority  
    2219.             if ( collectionTable != null ) {  
    2220.                 catalog = collectionTable.catalog();  
    2221.                 schema = collectionTable.schema();  
    2222.                 tableName = collectionTable.name();  
    2223.                 uniqueConstraints = collectionTable.uniqueConstraints();  
    2224.                 joins = collectionTable.joinColumns();  
    2225.                 inverseJoins = null;  
    2226.             }  
    2227.             else {  
    2228.                 catalog = assocTable.catalog();  
    2229.                 schema = assocTable.schema();  
    2230.                 tableName = assocTable.name();  
    2231.                 uniqueConstraints = assocTable.uniqueConstraints();  
    2232.                 joins = assocTable.joinColumns();  
    2233.                 inverseJoins = assocTable.inverseJoinColumns();  
    2234.             }  
    2235.   
    2236.             collectionBinder.setExplicitAssociationTable( true );  
    2237.   
    2238.             if ( !BinderHelper.isEmptyAnnotationValue( schema ) ) {  
    2239.                 associationTableBinder.setSchema( schema );  
    2240.             }  
    2241.             if ( !BinderHelper.isEmptyAnnotationValue( catalog ) ) {  
    2242.                 associationTableBinder.setCatalog( catalog );  
    2243.             }  
    2244.             if ( !BinderHelper.isEmptyAnnotationValue( tableName ) ) {  
    2245.                 associationTableBinder.setName( tableName );  
    2246.             }  
    2247.             associationTableBinder.setUniqueConstraints( uniqueConstraints );  
    2248.   
    2249.             //set check constaint in the second pass  
    2250.             annJoins = joins.length == 0 ? null : joins;  
    2251.             annInverseJoins = inverseJoins == null || inverseJoins.length == 0 ? null : inverseJoins;  
    2252.         }  
    2253.         else {  
    2254.             annJoins = null;  
    2255.             annInverseJoins = null;  
    2256.         }  
    2257.         Ejb3JoinColumn[] joinColumns = Ejb3JoinColumn.buildJoinTableJoinColumns(  
    2258.                 annJoins, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappedBy,  
    2259.                 mappings  
    2260.         );  
    2261.         Ejb3JoinColumn[] inverseJoinColumns = Ejb3JoinColumn.buildJoinTableJoinColumns(  
    2262.                 annInverseJoins, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(),  
    2263.                 mappedBy, mappings  
    2264.         );  
    2265.         associationTableBinder.setMappings( mappings );  
    2266.         collectionBinder.setTableBinder( associationTableBinder );  
    2267.         collectionBinder.setJoinColumns( joinColumns );  
    2268.         collectionBinder.setInverseJoinColumns( inverseJoinColumns );  
    2269.     }  
    2270.   
    2271.     private static PropertyBinder bindComponent(  
    2272.             PropertyData inferredData,  
    2273.             PropertyHolder propertyHolder,  
    2274.             AccessType propertyAccessor,  
    2275.             EntityBinder entityBinder,  
    2276.             boolean isIdentifierMapper,  
    2277.             Mappings mappings,  
    2278.             boolean isComponentEmbedded,  
    2279.             boolean isId, //is a identifier  
    2280.             Map<XClass, InheritanceState> inheritanceStatePerClass,  
    2281.             String referencedEntityName, //is a component who is overridden by a @MapsId  
    2282.             Ejb3JoinColumn[] columns) {  
    2283.         Component comp;  
    2284.         if ( referencedEntityName != null ) {  
    2285.             comp = createComponent( propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper, mappings );  
    2286.             SecondPass sp = new CopyIdentifierComponentSecondPass(  
    2287.                     comp,  
    2288.                     referencedEntityName,  
    2289.                     columns,  
    2290.                     mappings  
    2291.             );  
    2292.             mappings.addSecondPass( sp );  
    2293.         }  
    2294.         else {  
    2295.             comp = fillComponent(  
    2296.                     propertyHolder, inferredData, propertyAccessor, !isId, entityBinder,  
    2297.                     isComponentEmbedded, isIdentifierMapper,  
    2298.                     false, mappings, inheritanceStatePerClass  
    2299.             );  
    2300.         }  
    2301.         if ( isId ) {  
    2302.             comp.setKey( true );  
    2303.             if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {  
    2304.                 throw new AnnotationException(  
    2305.                         comp.getComponentClassName()  
    2306.                                 + " must not have @Id properties when used as an @EmbeddedId: "  
    2307.                                 + BinderHelper.getPath( propertyHolder, inferredData )  
    2308.                 );  
    2309.             }  
    2310.             if ( referencedEntityName == null && comp.getPropertySpan() == 0 ) {  
    2311.                 throw new AnnotationException(  
    2312.                         comp.getComponentClassName()  
    2313.                                 + " has no persistent id property: "  
    2314.                                 + BinderHelper.getPath( propertyHolder, inferredData )  
    2315.                 );  
    2316.             }  
    2317.         }  
    2318.         XProperty property = inferredData.getProperty();  
    2319.         setupComponentTuplizer( property, comp );  
    2320.         PropertyBinder binder = new PropertyBinder();  
    2321.         binder.setName( inferredData.getPropertyName() );  
    2322.         binder.setValue( comp );  
    2323.         binder.setProperty( inferredData.getProperty() );  
    2324.         binder.setAccessType( inferredData.getDefaultAccess() );  
    2325.         binder.setEmbedded( isComponentEmbedded );  
    2326.         binder.setHolder( propertyHolder );  
    2327.         binder.setId( isId );  
    2328.         binder.setEntityBinder( entityBinder );  
    2329.         binder.setInheritanceStatePerClass( inheritanceStatePerClass );  
    2330.         binder.setMappings( mappings );  
    2331.         binder.makePropertyAndBind();  
    2332.         return binder;  
    2333.     }  
    2334.   
    2335.     public static Component fillComponent(  
    2336.             PropertyHolder propertyHolder,  
    2337.             PropertyData inferredData,  
    2338.             AccessType propertyAccessor,  
    2339.             boolean isNullable,  
    2340.             EntityBinder entityBinder,  
    2341.             boolean isComponentEmbedded,  
    2342.             boolean isIdentifierMapper,  
    2343.             boolean inSecondPass,  
    2344.             Mappings mappings,  
    2345.             Map<XClass, InheritanceState> inheritanceStatePerClass) {  
    2346.         return fillComponent(  
    2347.                 propertyHolder, inferredData, null, propertyAccessor,  
    2348.                 isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings,  
    2349.                 inheritanceStatePerClass  
    2350.         );  
    2351.     }  
    2352.   
    2353.     public static Component fillComponent(  
    2354.             PropertyHolder propertyHolder,  
    2355.             PropertyData inferredData,  
    2356.             PropertyData baseInferredData, //base inferred data correspond to the entity reproducing inferredData's properties (ie IdClass)  
    2357.             AccessType propertyAccessor,  
    2358.             boolean isNullable,  
    2359.             EntityBinder entityBinder,  
    2360.             boolean isComponentEmbedded,  
    2361.             boolean isIdentifierMapper,  
    2362.             boolean inSecondPass,  
    2363.             Mappings mappings,  
    2364.             Map<XClass, InheritanceState> inheritanceStatePerClass) {  
    2365.         /** 
    2366.          * inSecondPass can only be used to apply right away the second pass of a composite-element 
    2367.          * Because it's a value type, there is no bidirectional association, hence second pass 
    2368.          * ordering does not matter 
    2369.          */  
    2370.         Component comp = createComponent( propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper, mappings );  
    2371.         String subpath = BinderHelper.getPath( propertyHolder, inferredData );  
    2372.         log.trace( "Binding component with path: {}", subpath );  
    2373.         PropertyHolder subHolder = PropertyHolderBuilder.buildPropertyHolder(  
    2374.                 comp, subpath,  
    2375.                 inferredData, propertyHolder, mappings  
    2376.         );  
    2377.   
    2378.         final XClass xClassProcessed = inferredData.getPropertyClass();  
    2379.         List<PropertyData> classElements = new ArrayList<PropertyData>();  
    2380.         XClass returnedClassOrElement = inferredData.getClassOrElement();  
    2381.   
    2382.         List<PropertyData> baseClassElements = null;  
    2383.         Map<String, PropertyData> orderedBaseClassElements = new HashMap<String, PropertyData>();  
    2384.         XClass baseReturnedClassOrElement;  
    2385.         if ( baseInferredData != null ) {  
    2386.             baseClassElements = new ArrayList<PropertyData>();  
    2387.             baseReturnedClassOrElement = baseInferredData.getClassOrElement();  
    2388.             bindTypeDefs( baseReturnedClassOrElement, mappings );  
    2389.             PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, xClassProcessed );  
    2390.             addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );  
    2391.             for ( PropertyData element : baseClassElements ) {  
    2392.                 orderedBaseClassElements.put( element.getPropertyName(), element );  
    2393.             }  
    2394.         }  
    2395.   
    2396.         //embeddable elements can have type defs  
    2397.         bindTypeDefs( returnedClassOrElement, mappings );  
    2398.         PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement, xClassProcessed );  
    2399.         addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );  
    2400.   
    2401.         //add elements of the embeddable superclass  
    2402.         XClass superClass = xClassProcessed.getSuperclass();  
    2403.         while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) {  
    2404.             //FIXME: proper support of typevariables incl var resolved at upper levels  
    2405.             propContainer = new PropertyContainer( superClass, xClassProcessed );  
    2406.             addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );  
    2407.             superClass = superClass.getSuperclass();  
    2408.         }  
    2409.         if ( baseClassElements != null ) {  
    2410.             //useful to avoid breaking pre JPA 2 mappings  
    2411.             if ( !hasAnnotationsOnIdClass( xClassProcessed ) ) {  
    2412.                 for ( int i = 0; i < classElements.size(); i++ ) {  
    2413.                     final PropertyData idClassPropertyData = classElements.get( i );  
    2414.                     final PropertyData entityPropertyData = orderedBaseClassElements.get( idClassPropertyData.getPropertyName() );  
    2415.                     if ( propertyHolder.isInIdClass() ) {  
    2416.                         if ( entityPropertyData == null ) {  
    2417.                             throw new AnnotationException(  
    2418.                                     "Property of @IdClass not found in entity "  
    2419.                                             + baseInferredData.getPropertyClass().getName() + ": "  
    2420.                                             + idClassPropertyData.getPropertyName()  
    2421.                             );  
    2422.                         }  
    2423.                         final boolean hasXToOneAnnotation = entityPropertyData.getProperty()  
    2424.                                 .isAnnotationPresent( ManyToOne.class )  
    2425.                                 || entityPropertyData.getProperty().isAnnotationPresent( OneToOne.class );  
    2426.                         final boolean isOfDifferentType = !entityPropertyData.getClassOrElement()  
    2427.                                 .equals( idClassPropertyData.getClassOrElement() );  
    2428.                         if ( hasXToOneAnnotation && isOfDifferentType ) {  
    2429.                             //don't replace here as we need to use the actual original return type  
    2430.                             //the annotation overriding will be dealt with by a mechanism similar to @MapsId  
    2431.                         }  
    2432.                         else {  
    2433.                             classElements.set( i, entityPropertyData );  //this works since they are in the same order  
    2434.                         }  
    2435.                     }  
    2436.                     else {  
    2437.                         classElements.set( i, entityPropertyData );  //this works since they are in the same order  
    2438.                     }  
    2439.                 }  
    2440.             }  
    2441.         }  
    2442.         for ( PropertyData propertyAnnotatedElement : classElements ) {  
    2443.             processElementAnnotations(  
    2444.                     subHolder, isNullable ?  
    2445.                             Nullability.NO_CONSTRAINT :  
    2446.                             Nullability.FORCED_NOT_NULL,  
    2447.                     propertyAnnotatedElement,  
    2448.                     new HashMap<String, IdGenerator>(), entityBinder, isIdentifierMapper, isComponentEmbedded,  
    2449.                     inSecondPass, mappings, inheritanceStatePerClass  
    2450.             );  
    2451.   
    2452.             XProperty property = propertyAnnotatedElement.getProperty();  
    2453.             if ( property.isAnnotationPresent( GeneratedValue.class ) &&  
    2454.                     property.isAnnotationPresent( Id.class ) ) {  
    2455.                 //clone classGenerator and override with local values  
    2456.                 Map<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();  
    2457.                 localGenerators.putAll( buildLocalGenerators( property, mappings ) );  
    2458.   
    2459.                 GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );  
    2460.                 String generatorType = generatedValue != null ? generatorType(  
    2461.                         generatedValue.strategy(), mappings  
    2462.                 ) : "assigned";  
    2463.                 String generator = generatedValue != null ? generatedValue.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;  
    2464.   
    2465.                 BinderHelper.makeIdGenerator(  
    2466.                         ( SimpleValue ) comp.getProperty( property.getName() ).getValue(),  
    2467.                         generatorType,  
    2468.                         generator,  
    2469.                         mappings,  
    2470.                         localGenerators  
    2471.                 );  
    2472.             }  
    2473.   
    2474.         }  
    2475.         return comp;  
    2476.     }  
    2477.   
    2478.     public static Component createComponent(  
    2479.             PropertyHolder propertyHolder,  
    2480.             PropertyData inferredData,  
    2481.             boolean isComponentEmbedded,  
    2482.             boolean isIdentifierMapper,  
    2483.             Mappings mappings) {  
    2484.         Component comp = new Component( mappings, propertyHolder.getPersistentClass() );  
    2485.         comp.setEmbedded( isComponentEmbedded );  
    2486.         //yuk  
    2487.         comp.setTable( propertyHolder.getTable() );  
    2488.         //FIXME shouldn't identifier mapper use getClassOrElementName? Need to be checked.  
    2489.         if ( isIdentifierMapper || ( isComponentEmbedded && inferredData.getPropertyName() == null ) ) {  
    2490.             comp.setComponentClassName( comp.getOwner().getClassName() );  
    2491.         }  
    2492.         else {  
    2493.             comp.setComponentClassName( inferredData.getClassOrElementName() );  
    2494.         }  
    2495.         comp.setNodeName( inferredData.getPropertyName() );  
    2496.         return comp;  
    2497.     }  
    2498.   
    2499.     private static void bindIdClass(  
    2500.             String generatorType,  
    2501.             String generatorName,  
    2502.             PropertyData inferredData,  
    2503.             PropertyData baseInferredData,  
    2504.             Ejb3Column[] columns,  
    2505.             PropertyHolder propertyHolder,  
    2506.             boolean isComposite,  
    2507.             AccessType propertyAccessor,  
    2508.             EntityBinder entityBinder,  
    2509.             boolean isEmbedded,  
    2510.             boolean isIdentifierMapper,  
    2511.             Mappings mappings,  
    2512.             Map<XClass, InheritanceState> inheritanceStatePerClass) {  
    2513.   
    2514.         /* 
    2515.          * Fill simple value and property since and Id is a property 
    2516.          */  
    2517.         PersistentClass persistentClass = propertyHolder.getPersistentClass();  
    2518.         if ( !( persistentClass instanceof RootClass ) ) {  
    2519.             throw new AnnotationException(  
    2520.                     "Unable to define/override @Id(s) on a subclass: "  
    2521.                             + propertyHolder.getEntityName()  
    2522.             );  
    2523.         }  
    2524.         RootClass rootClass = ( RootClass ) persistentClass;  
    2525.         String persistentClassName = rootClass.getClassName();  
    2526.         SimpleValue id;  
    2527.         final String propertyName = inferredData.getPropertyName();  
    2528.         HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();  
    2529.         if ( isComposite ) {  
    2530.             id = fillComponent(  
    2531.                     propertyHolder, inferredData, baseInferredData, propertyAccessor,  
    2532.                     false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass  
    2533.             );  
    2534.             Component componentId = ( Component ) id;  
    2535.             componentId.setKey( true );  
    2536.             if ( rootClass.getIdentifier() != null ) {  
    2537.                 throw new AnnotationException( componentId.getComponentClassName() + " must not have @Id properties when used as an @EmbeddedId" );  
    2538.             }  
    2539.             if ( componentId.getPropertySpan() == 0 ) {  
    2540.                 throw new AnnotationException( componentId.getComponentClassName() + " has no persistent id property" );  
    2541.             }  
    2542.             //tuplizers  
    2543.             XProperty property = inferredData.getProperty();  
    2544.             setupComponentTuplizer( property, componentId );  
    2545.         }  
    2546.         else {  
    2547.             //TODO I think this branch is never used. Remove.  
    2548.   
    2549.             for ( Ejb3Column column : columns ) {  
    2550.                 column.forceNotNull(); //this is an id  
    2551.             }  
    2552.             SimpleValueBinder value = new SimpleValueBinder();  
    2553.             value.setPropertyName( propertyName );  
    2554.             value.setReturnedClassName( inferredData.getTypeName() );  
    2555.             value.setColumns( columns );  
    2556.             value.setPersistentClassName( persistentClassName );  
    2557.             value.setMappings( mappings );  
    2558.             value.setType( inferredData.getProperty(), inferredData.getClassOrElement() );  
    2559.             id = value.make();  
    2560.         }  
    2561.         rootClass.setIdentifier( id );  
    2562.         BinderHelper.makeIdGenerator( id, generatorType, generatorName, mappings, localGenerators );  
    2563.         if ( isEmbedded ) {  
    2564.             rootClass.setEmbeddedIdentifier( inferredData.getPropertyClass() == null );  
    2565.         }  
    2566.         else {  
    2567.             PropertyBinder binder = new PropertyBinder();  
    2568.             binder.setName( propertyName );  
    2569.             binder.setValue( id );  
    2570.             binder.setAccessType( inferredData.getDefaultAccess() );  
    2571.             binder.setProperty( inferredData.getProperty() );  
    2572.             Property prop = binder.makeProperty();  
    2573.             rootClass.setIdentifierProperty( prop );  
    2574.             //if the id property is on a superclass, update the metamodel  
    2575.             final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(  
    2576.                     inferredData.getDeclaringClass(),  
    2577.                     inheritanceStatePerClass,  
    2578.                     mappings  
    2579.             );  
    2580.             if ( superclass != null ) {  
    2581.                 superclass.setDeclaredIdentifierProperty( prop );  
    2582.             }  
    2583.             else {  
    2584.                 //we know the property is on the actual entity  
    2585.                 rootClass.setDeclaredIdentifierProperty( prop );  
    2586.             }  
    2587.         }  
    2588.     }  
    2589.   
    2590.     private static PropertyData getUniqueIdPropertyFromBaseClass(  
    2591.             PropertyData inferredData,  
    2592.             PropertyData baseInferredData,  
    2593.             AccessType propertyAccessor,  
    2594.             Mappings mappings) {  
    2595.         List<PropertyData> baseClassElements = new ArrayList<PropertyData>();  
    2596.         XClass baseReturnedClassOrElement = baseInferredData.getClassOrElement();  
    2597.         PropertyContainer propContainer = new PropertyContainer(  
    2598.                 baseReturnedClassOrElement, inferredData.getPropertyClass()  
    2599.         );  
    2600.         addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );  
    2601.         //Id properties are on top and there is only one  
    2602.         return baseClassElements.get( 0 );  
    2603.     }  
    2604.   
    2605.     private static void setupComponentTuplizer(XProperty property, Component component) {  
    2606.         if ( property == null ) {  
    2607.             return;  
    2608.         }  
    2609.         if ( property.isAnnotationPresent( Tuplizers.class ) ) {  
    2610.             for ( Tuplizer tuplizer : property.getAnnotation( Tuplizers.class ).value() ) {  
    2611.                 EntityMode mode = EntityMode.parse( tuplizer.entityMode() );  
    2612.                 component.addTuplizer( mode, tuplizer.impl().getName() );  
    2613.             }  
    2614.         }  
    2615.         if ( property.isAnnotationPresent( Tuplizer.class ) ) {  
    2616.             Tuplizer tuplizer = property.getAnnotation( Tuplizer.class );  
    2617.             EntityMode mode = EntityMode.parse( tuplizer.entityMode() );  
    2618.             component.addTuplizer( mode, tuplizer.impl().getName() );  
    2619.         }  
    2620.     }  
    2621.   
    2622.     private static void bindManyToOne(  
    2623.             String cascadeStrategy,  
    2624.             Ejb3JoinColumn[] columns,  
    2625.             boolean optional,  
    2626.             boolean ignoreNotFound,  
    2627.             boolean cascadeOnDelete,  
    2628.             XClass targetEntity,  
    2629.             PropertyHolder propertyHolder,  
    2630.             PropertyData inferredData,  
    2631.             boolean unique,  
    2632.             boolean isIdentifierMapper,  
    2633.             boolean inSecondPass,  
    2634.             PropertyBinder propertyBinder,  
    2635.             Mappings mappings) {  
    2636.         //All FK columns should be in the same table  
    2637.         org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne( mappings, columns[0].getTable() );  
    2638.         // This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne  
    2639.         if ( unique ) {  
    2640.             value.markAsLogicalOneToOne();  
    2641.         }  
    2642.         value.setReferencedEntityName( ToOneBinder.getReferenceEntityName( inferredData, targetEntity, mappings ) );  
    2643.         final XProperty property = inferredData.getProperty();  
    2644.         defineFetchingStrategy( value, property );  
    2645.         //value.setFetchMode( fetchMode );  
    2646.         value.setIgnoreNotFound( ignoreNotFound );  
    2647.         value.setCascadeDeleteEnabled( cascadeOnDelete );  
    2648.         //value.setLazy( fetchMode != FetchMode.JOIN );  
    2649.         if ( !optional ) {  
    2650.             for ( Ejb3JoinColumn column : columns ) {  
    2651.                 column.setNullable( false );  
    2652.             }  
    2653.         }  
    2654.         if ( property.isAnnotationPresent( MapsId.class ) ) {  
    2655.             //read only  
    2656.             for ( Ejb3JoinColumn column : columns ) {  
    2657.                 column.setInsertable( false );  
    2658.                 column.setUpdatable( false );  
    2659.             }  
    2660.         }  
    2661.   
    2662.         //Make sure that JPA1 key-many-to-one columns are read only tooj  
    2663.         boolean hasSpecjManyToOne=false;  
    2664.         if ( mappings.isSpecjProprietarySyntaxEnabled() ) {  
    2665.             String columnName = "";  
    2666.             for ( XProperty prop : inferredData.getDeclaringClass()  
    2667.                     .getDeclaredProperties( AccessType.FIELD.getType() ) ) {  
    2668.                 if ( prop.isAnnotationPresent( Id.class ) && prop.isAnnotationPresent( Column.class ) ) {  
    2669.                     columnName = prop.getAnnotation( Column.class ).name();  
    2670.                 }  
    2671.   
    2672.                 final JoinColumn joinColumn = property.getAnnotation( JoinColumn.class );  
    2673.                 if ( property.isAnnotationPresent( ManyToOne.class ) && joinColumn != null  
    2674.                         && ! BinderHelper.isEmptyAnnotationValue( joinColumn.name() )  
    2675.                         && joinColumn.name().equals( columnName )  
    2676.                         && !property.isAnnotationPresent( MapsId.class ) ) {  
    2677.                    hasSpecjManyToOne = true;  
    2678.                     for ( Ejb3JoinColumn column : columns ) {  
    2679.                         column.setInsertable( false );  
    2680.                         column.setUpdatable( false );  
    2681.                     }  
    2682.                 }  
    2683.             }  
    2684.   
    2685.         }  
    2686.         value.setTypeName( inferredData.getClassOrElementName() );  
    2687.         final String propertyName = inferredData.getPropertyName();  
    2688.         value.setTypeUsingReflection( propertyHolder.getClassName(), propertyName );  
    2689.   
    2690.         ForeignKey fk = property.getAnnotation( ForeignKey.class );  
    2691.         String fkName = fk != null ?  
    2692.                 fk.name() :  
    2693.                 "";  
    2694.         if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) {  
    2695.             value.setForeignKeyName( fkName );  
    2696.         }  
    2697.   
    2698.         String path = propertyHolder.getPath() + "." + propertyName;  
    2699.         FkSecondPass secondPass = new ToOneFkSecondPass(  
    2700.                 value, columns,  
    2701.                 !optional && unique, //cannot have nullable and unique on certain DBs like Derby  
    2702.                 propertyHolder.getEntityOwnerClassName(),  
    2703.                 path, mappings  
    2704.         );  
    2705.         if ( inSecondPass ) {  
    2706.             secondPass.doSecondPass( mappings.getClasses() );  
    2707.         }  
    2708.         else {  
    2709.             mappings.addSecondPass(  
    2710.                     secondPass  
    2711.             );  
    2712.         }  
    2713.         Ejb3Column.checkPropertyConsistency( columns, propertyHolder.getEntityName() + propertyName );  
    2714.         //PropertyBinder binder = new PropertyBinder();  
    2715.         propertyBinder.setName( propertyName );  
    2716.         propertyBinder.setValue( value );  
    2717.         //binder.setCascade(cascadeStrategy);  
    2718.         if ( isIdentifierMapper ) {  
    2719.             propertyBinder.setInsertable( false );  
    2720.             propertyBinder.setUpdatable( false );  
    2721.         }  
    2722.         else if (hasSpecjManyToOne) {  
    2723.            propertyBinder.setInsertable( false );  
    2724.            propertyBinder.setUpdatable( false );  
    2725.         }  
    2726.         else {  
    2727.             propertyBinder.setInsertable( columns[0].isInsertable() );  
    2728.             propertyBinder.setUpdatable( columns[0].isUpdatable() );  
    2729.         }  
    2730.         propertyBinder.setColumns( columns );  
    2731.         propertyBinder.setAccessType( inferredData.getDefaultAccess() );  
    2732.         propertyBinder.setCascade( cascadeStrategy );  
    2733.         propertyBinder.setProperty( property );  
    2734.         propertyBinder.setXToMany( true );  
    2735.         propertyBinder.makePropertyAndBind();  
    2736.     }  
    2737.   
    2738.     protected static void defineFetchingStrategy(ToOne toOne, XProperty property) {  
    2739.         LazyToOne lazy = property.getAnnotation( LazyToOne.class );  
    2740.         Fetch fetch = property.getAnnotation( Fetch.class );  
    2741.         ManyToOne manyToOne = property.getAnnotation( ManyToOne.class );  
    2742.         OneToOne oneToOne = property.getAnnotation( OneToOne.class );  
    2743.         FetchType fetchType;  
    2744.         if ( manyToOne != null ) {  
    2745.             fetchType = manyToOne.fetch();  
    2746.         }  
    2747.         else if ( oneToOne != null ) {  
    2748.             fetchType = oneToOne.fetch();  
    2749.         }  
    2750.         else {  
    2751.             throw new AssertionFailure(  
    2752.                     "Define fetch strategy on a property not annotated with @OneToMany nor @OneToOne"  
    2753.             );  
    2754.         }  
    2755.         if ( lazy != null ) {  
    2756.             toOne.setLazy( !( lazy.value() == LazyToOneOption.FALSE ) );  
    2757.             toOne.setUnwrapProxy( ( lazy.value() == LazyToOneOption.NO_PROXY ) );  
    2758.         }  
    2759.         else {  
    2760.             toOne.setLazy( fetchType == FetchType.LAZY );  
    2761.             toOne.setUnwrapProxy( false );  
    2762.         }  
    2763.         if ( fetch != null ) {  
    2764.             if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) {  
    2765.                 toOne.setFetchMode( FetchMode.JOIN );  
    2766.                 toOne.setLazy( false );  
    2767.                 toOne.setUnwrapProxy( false );  
    2768.             }  
    2769.             else if ( fetch.value() == org.hibernate.annotations.FetchMode.SELECT ) {  
    2770.                 toOne.setFetchMode( FetchMode.SELECT );  
    2771.             }  
    2772.             else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) {  
    2773.                 throw new AnnotationException( "Use of FetchMode.SUBSELECT not allowed on ToOne associations" );  
    2774.             }  
    2775.             else {  
    2776.                 throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() );  
    2777.             }  
    2778.         }  
    2779.         else {  
    2780.             toOne.setFetchMode( getFetchMode( fetchType ) );  
    2781.         }  
    2782.     }  
    2783.   
    2784.     private static void bindOneToOne(  
    2785.             String cascadeStrategy,  
    2786.             Ejb3JoinColumn[] joinColumns,  
    2787.             boolean optional,  
    2788.             FetchMode fetchMode,  
    2789.             boolean ignoreNotFound,  
    2790.             boolean cascadeOnDelete,  
    2791.             XClass targetEntity,  
    2792.             PropertyHolder propertyHolder,  
    2793.             PropertyData inferredData, String mappedBy,  
    2794.             boolean trueOneToOne,  
    2795.             boolean isIdentifierMapper,  
    2796.             boolean inSecondPass,  
    2797.             PropertyBinder propertyBinder,  
    2798.             Mappings mappings) {  
    2799.         //column.getTable() => persistentClass.getTable()  
    2800.         final String propertyName = inferredData.getPropertyName();  
    2801.         log.trace( "Fetching {} with {}", propertyName, fetchMode );  
    2802.         boolean mapToPK = true;  
    2803.         if ( !trueOneToOne ) {  
    2804.             //try to find a hidden true one to one (FK == PK columns)  
    2805.             KeyValue identifier = propertyHolder.getIdentifier();  
    2806.             if ( identifier == null ) {  
    2807.                 //this is a @OneToOne in a @EmbeddedId (the persistentClass.identifier is not set yet, it's being built)  
    2808.                 //by definition the PK cannot refers to itself so it cannot map to itself  
    2809.                 mapToPK = false;  
    2810.             }  
    2811.             else {  
    2812.                 Iterator idColumns = identifier.getColumnIterator();  
    2813.                 List<String> idColumnNames = new ArrayList<String>();  
    2814.                 org.hibernate.mapping.Column currentColumn;  
    2815.                 if ( identifier.getColumnSpan() != joinColumns.length ) {  
    2816.                     mapToPK = false;  
    2817.                 }  
    2818.                 else {  
    2819.                     while ( idColumns.hasNext() ) {  
    2820.                         currentColumn = ( org.hibernate.mapping.Column ) idColumns.next();  
    2821.                         idColumnNames.add( currentColumn.getName() );  
    2822.                     }  
    2823.                     for ( Ejb3JoinColumn col : joinColumns ) {  
    2824.                         if ( !idColumnNames.contains( col.getMappingColumn().getName() ) ) {  
    2825.                             mapToPK = false;  
    2826.                             break;  
    2827.                         }  
    2828.                     }  
    2829.                 }  
    2830.             }  
    2831.         }  
    2832.         if ( trueOneToOne || mapToPK || !BinderHelper.isEmptyAnnotationValue( mappedBy ) ) {  
    2833.             //is a true one-to-one  
    2834.             //FIXME referencedColumnName ignored => ordering may fail.  
    2835.             OneToOneSecondPass secondPass = new OneToOneSecondPass(  
    2836.                     mappedBy,  
    2837.                     propertyHolder.getEntityName(),  
    2838.                     propertyName,  
    2839.                     propertyHolder, inferredData, targetEntity, ignoreNotFound, cascadeOnDelete,  
    2840.                     optional, cascadeStrategy, joinColumns, mappings  
    2841.             );  
    2842.             if ( inSecondPass ) {  
    2843.                 secondPass.doSecondPass( mappings.getClasses() );  
    2844.             }  
    2845.             else {  
    2846.                 mappings.addSecondPass(  
    2847.                         secondPass, BinderHelper.isEmptyAnnotationValue( mappedBy )  
    2848.                 );  
    2849.             }  
    2850.         }  
    2851.         else {  
    2852.             //has a FK on the table  
    2853.             bindManyToOne(  
    2854.                     cascadeStrategy, joinColumns, optional, ignoreNotFound, cascadeOnDelete,  
    2855.                     targetEntity,  
    2856.                     propertyHolder, inferredData, true, isIdentifierMapper, inSecondPass,  
    2857.                     propertyBinder, mappings  
    2858.             );  
    2859.         }  
    2860.     }  
    2861.   
    2862.     private static void bindAny(  
    2863.             String cascadeStrategy,  
    2864.             Ejb3JoinColumn[] columns,  
    2865.             boolean cascadeOnDelete,  
    2866.             Nullability nullability,  
    2867.             PropertyHolder propertyHolder,  
    2868.             PropertyData inferredData,  
    2869.             EntityBinder entityBinder,  
    2870.             boolean isIdentifierMapper,  
    2871.             Mappings mappings) {  
    2872.         org.hibernate.annotations.Any anyAnn = inferredData.getProperty()  
    2873.                 .getAnnotation( org.hibernate.annotations.Any.class );  
    2874.         if ( anyAnn == null ) {  
    2875.             throw new AssertionFailure(  
    2876.                     "Missing @Any annotation: "  
    2877.                             + BinderHelper.getPath( propertyHolder, inferredData )  
    2878.             );  
    2879.         }  
    2880.         Any value = BinderHelper.buildAnyValue(  
    2881.                 anyAnn.metaDef(), columns, anyAnn.metaColumn(), inferredData,  
    2882.                 cascadeOnDelete, nullability, propertyHolder, entityBinder, anyAnn.optional(), mappings  
    2883.         );  
    2884.   
    2885.         PropertyBinder binder = new PropertyBinder();  
    2886.         binder.setName( inferredData.getPropertyName() );  
    2887.         binder.setValue( value );  
    2888.   
    2889.         binder.setLazy( anyAnn.fetch() == FetchType.LAZY );  
    2890.         //binder.setCascade(cascadeStrategy);  
    2891.         if ( isIdentifierMapper ) {  
    2892.             binder.setInsertable( false );  
    2893.             binder.setUpdatable( false );  
    2894.         }  
    2895.         else {  
    2896.             binder.setInsertable( columns[0].isInsertable() );  
    2897.             binder.setUpdatable( columns[0].isUpdatable() );  
    2898.         }  
    2899.         binder.setAccessType( inferredData.getDefaultAccess() );  
    2900.         binder.setCascade( cascadeStrategy );  
    2901.         Property prop = binder.makeProperty();  
    2902.         //composite FK columns are in the same table so its OK  
    2903.         propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );  
    2904.     }  
    2905.   
    2906.     private static String generatorType(GenerationType generatorEnum, Mappings mappings) {  
    2907.         boolean useNewGeneratorMappings = mappings.useNewGeneratorMappings();  
    2908.         switch ( generatorEnum ) {  
    2909.             case IDENTITY:  
    2910.                 return "identity";  
    2911.             case AUTO:  
    2912.                 return useNewGeneratorMappings  
    2913.                         ? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()  
    2914.                         : "native";  
    2915.             case TABLE:  
    2916.                 return useNewGeneratorMappings  
    2917.                         ? org.hibernate.id.enhanced.TableGenerator.class.getName()  
    2918.                         : MultipleHiLoPerTableGenerator.class.getName();  
    2919.             case SEQUENCE:  
    2920.                 return useNewGeneratorMappings  
    2921.                         ? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()  
    2922.                         : "seqhilo";  
    2923.         }  
    2924.         throw new AssertionFailure( "Unknown GeneratorType: " + generatorEnum );  
    2925.     }  
    2926.   
    2927.     private static EnumSet<CascadeType> convertToHibernateCascadeType(javax.persistence.CascadeType[] ejbCascades) {  
    2928.         EnumSet<CascadeType> hibernateCascadeSet = EnumSet.noneOf( CascadeType.class );  
    2929.         if ( ejbCascades != null && ejbCascades.length > 0 ) {  
    2930.             for ( javax.persistence.CascadeType cascade : ejbCascades ) {  
    2931.                 switch ( cascade ) {  
    2932.                     case ALL:  
    2933.                         hibernateCascadeSet.add( CascadeType.ALL );  
    2934.                         break;  
    2935.                     case PERSIST:  
    2936.                         hibernateCascadeSet.add( CascadeType.PERSIST );  
    2937.                         break;  
    2938.                     case MERGE:  
    2939.                         hibernateCascadeSet.add( CascadeType.MERGE );  
    2940.                         break;  
    2941.                     case REMOVE:  
    2942.                         hibernateCascadeSet.add( CascadeType.REMOVE );  
    2943.                         break;  
    2944.                     case REFRESH:  
    2945.                         hibernateCascadeSet.add( CascadeType.REFRESH );  
    2946.                         break;  
    2947.                     case DETACH:  
    2948.                         hibernateCascadeSet.add( CascadeType.DETACH );  
    2949.                         break;  
    2950.                 }  
    2951.             }  
    2952.         }  
    2953.   
    2954.         return hibernateCascadeSet;  
    2955.     }  
    2956.   
    2957.     private static String getCascadeStrategy(  
    2958.             javax.persistence.CascadeType[] ejbCascades,  
    2959.             Cascade hibernateCascadeAnnotation,  
    2960.             boolean orphanRemoval,  
    2961.             boolean forcePersist) {  
    2962.         EnumSet<CascadeType> hibernateCascadeSet = convertToHibernateCascadeType( ejbCascades );  
    2963.         CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null ?  
    2964.                 null :  
    2965.                 hibernateCascadeAnnotation.value();  
    2966.   
    2967.         if ( hibernateCascades != null && hibernateCascades.length > 0 ) {  
    2968.             hibernateCascadeSet.addAll( Arrays.asList( hibernateCascades ) );  
    2969.         }  
    2970.   
    2971.         if ( orphanRemoval ) {  
    2972.             hibernateCascadeSet.add( CascadeType.DELETE_ORPHAN );  
    2973.             hibernateCascadeSet.add( CascadeType.REMOVE );  
    2974.         }  
    2975.         if ( forcePersist ) {  
    2976.             hibernateCascadeSet.add( CascadeType.PERSIST );  
    2977.         }  
    2978.   
    2979.         StringBuilder cascade = new StringBuilder();  
    2980.         for ( CascadeType aHibernateCascadeSet : hibernateCascadeSet ) {  
    2981.             switch ( aHibernateCascadeSet ) {  
    2982.                 case ALL:  
    2983.                     cascade.append( "," ).append( "all" );  
    2984.                     break;  
    2985.                 case SAVE_UPDATE:  
    2986.                     cascade.append( "," ).append( "save-update" );  
    2987.                     break;  
    2988.                 case PERSIST:  
    2989.                     cascade.append( "," ).append( "persist" );  
    2990.                     break;  
    2991.                 case MERGE:  
    2992.                     cascade.append( "," ).append( "merge" );  
    2993.                     break;  
    2994.                 case LOCK:  
    2995.                     cascade.append( "," ).append( "lock" );  
    2996.                     break;  
    2997.                 case REFRESH:  
    2998.                     cascade.append( "," ).append( "refresh" );  
    2999.                     break;  
    3000.                 case REPLICATE:  
    3001.                     cascade.append( "," ).append( "replicate" );  
    3002.                     break;  
    3003.                 case EVICT:  
    3004.                 case DETACH:  
    3005.                     cascade.append( "," ).append( "evict" );  
    3006.                     break;  
    3007.                 case DELETE:  
    3008.                     cascade.append( "," ).append( "delete" );  
    3009.                     break;  
    3010.                 case DELETE_ORPHAN:  
    3011.                     cascade.append( "," ).append( "delete-orphan" );  
    3012.                     break;  
    3013.                 case REMOVE:  
    3014.                     cascade.append( "," ).append( "delete" );  
    3015.                     break;  
    3016.             }  
    3017.         }  
    3018.         return cascade.length() > 0 ?  
    3019.                 cascade.substring( 1 ) :  
    3020.                 "none";  
    3021.     }  
    3022.   
    3023.     public static FetchMode getFetchMode(FetchType fetch) {  
    3024.         if ( fetch == FetchType.EAGER ) {  
    3025.             return FetchMode.JOIN;  
    3026.         }  
    3027.         else {  
    3028.             return FetchMode.SELECT;  
    3029.         }  
    3030.     }  
    3031.   
    3032.     private static HashMap<String, IdGenerator> buildLocalGenerators(XAnnotatedElement annElt, Mappings mappings) {  
    3033.         HashMap<String, IdGenerator> generators = new HashMap<String, IdGenerator>();  
    3034.         TableGenerator tabGen = annElt.getAnnotation( TableGenerator.class );  
    3035.         SequenceGenerator seqGen = annElt.getAnnotation( SequenceGenerator.class );  
    3036.         GenericGenerator genGen = annElt.getAnnotation( GenericGenerator.class );  
    3037.         if ( tabGen != null ) {  
    3038.             IdGenerator idGen = buildIdGenerator( tabGen, mappings );  
    3039.             generators.put( idGen.getName(), idGen );  
    3040.         }  
    3041.         if ( seqGen != null ) {  
    3042.             IdGenerator idGen = buildIdGenerator( seqGen, mappings );  
    3043.             generators.put( idGen.getName(), idGen );  
    3044.         }  
    3045.         if ( genGen != null ) {  
    3046.             IdGenerator idGen = buildIdGenerator( genGen, mappings );  
    3047.             generators.put( idGen.getName(), idGen );  
    3048.         }  
    3049.         return generators;  
    3050.     }  
    3051.   
    3052.     public static boolean isDefault(XClass clazz, Mappings mappings) {  
    3053.         return mappings.getReflectionManager().equals( clazz, void.class );  
    3054.     }  
    3055.   
    3056.     /** 
    3057.      * For the mapped entities build some temporary data-structure containing information about the 
    3058.      * inheritance status of a class. 
    3059.      * 
    3060.      * @param orderedClasses Order list of all annotated entities and their mapped superclasses 
    3061.      * 
    3062.      * @return A map of {@code InheritanceState}s keyed against their {@code XClass}. 
    3063.      */  
    3064.     public static Map<XClass, InheritanceState> buildInheritanceStates(  
    3065.             List<XClass> orderedClasses,  
    3066.             Mappings mappings) {  
    3067.         ReflectionManager reflectionManager = mappings.getReflectionManager();  
    3068.         Map<XClass, InheritanceState> inheritanceStatePerClass = new HashMap<XClass, InheritanceState>(  
    3069.                 orderedClasses.size()  
    3070.         );  
    3071.         for ( XClass clazz : orderedClasses ) {  
    3072.             InheritanceState superclassState = InheritanceState.getSuperclassInheritanceState(  
    3073.                     clazz, inheritanceStatePerClass  
    3074.             );  
    3075.             InheritanceState state = new InheritanceState( clazz, inheritanceStatePerClass, mappings );  
    3076.             if ( superclassState != null ) {  
    3077.                 //the classes are ordered thus preventing an NPE  
    3078.                 //FIXME if an entity has subclasses annotated @MappedSperclass wo sub @Entity this is wrong  
    3079.                 superclassState.setHasSiblings( true );  
    3080.                 InheritanceState superEntityState = InheritanceState.getInheritanceStateOfSuperEntity(  
    3081.                         clazz, inheritanceStatePerClass  
    3082.                 );  
    3083.                 state.setHasParents( superEntityState != null );  
    3084.                 final boolean nonDefault = state.getType() != null && !InheritanceType.SINGLE_TABLE  
    3085.                         .equals( state.getType() );  
    3086.                 if ( superclassState.getType() != null ) {  
    3087.                     final boolean mixingStrategy = state.getType() != null && !state.getType()  
    3088.                             .equals( superclassState.getType() );  
    3089.                     if ( nonDefault && mixingStrategy ) {  
    3090.                         log.warn(  
    3091.                                 "Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: {}",  
    3092.                                 clazz.getName()  
    3093.                         );  
    3094.                     }  
    3095.                     state.setType( superclassState.getType() );  
    3096.                 }  
    3097.             }  
    3098.             inheritanceStatePerClass.put( clazz, state );  
    3099.         }  
    3100.         return inheritanceStatePerClass;  
    3101.     }  
    3102.   
    3103.     private static boolean hasAnnotationsOnIdClass(XClass idClass) {  
    3104. //      if(idClass.getAnnotation(Embeddable.class) != null)  
    3105. //          return true;  
    3106.   
    3107.         List<XProperty> properties = idClass.getDeclaredProperties( XClass.ACCESS_FIELD );  
    3108.         for ( XProperty property : properties ) {  
    3109.             if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( OneToMany.class ) ||  
    3110.                     property.isAnnotationPresent( ManyToOne.class ) || property.isAnnotationPresent( Id.class ) ||  
    3111.                     property.isAnnotationPresent( GeneratedValue.class ) || property.isAnnotationPresent( OneToOne.class ) ||  
    3112.                     property.isAnnotationPresent( ManyToMany.class )  
    3113.                     ) {  
    3114.                 return true;  
    3115.             }  
    3116.         }  
    3117.         List<XMethod> methods = idClass.getDeclaredMethods();  
    3118.         for ( XMethod method : methods ) {  
    3119.             if ( method.isAnnotationPresent( Column.class ) || method.isAnnotationPresent( OneToMany.class ) ||  
    3120.                     method.isAnnotationPresent( ManyToOne.class ) || method.isAnnotationPresent( Id.class ) ||  
    3121.                     method.isAnnotationPresent( GeneratedValue.class ) || method.isAnnotationPresent( OneToOne.class ) ||  
    3122.                     method.isAnnotationPresent( ManyToMany.class )  
    3123.                     ) {  
    3124.                 return true;  
    3125.             }  
    3126.         }  
    3127.         return false;  
    3128.     }  
    3129.   


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM