如果使用的是xml方式配置,则使用comment即可:
<property name="name" >
<column name="name_col">
<comment>我是注释</comment>
</column>
</property>
下面的方法是修改hibernate3.6.10源码、添加注解配置的处理信息:
- package org.hibernate.cfg;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target({ElementType.TYPE,ElementType.FIELD})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Comment {
- String value() default "";
- }
- package org.hibernate.cfg;
- import org.hibernate.annotations.common.reflection.XClass;
- import org.hibernate.annotations.common.reflection.XProperty;
- import org.hibernate.cfg.Ejb3Column;
- import org.hibernate.mapping.PersistentClass;
- public class CommentBinder {
- public static void bindTableComment(XClass clazzToProcess, PersistentClass persistentClass) {
- //System.out.println("处理表名注释!");
- if (clazzToProcess.isAnnotationPresent(Comment.class)) {
- String tableComment = clazzToProcess.getAnnotation(Comment.class).value();
- persistentClass.getTable().setComment(tableComment);
- }
- }
- public static void bindColumnComment(XProperty property, Ejb3Column[] columns) {
- //System.out.println("处理多字段注释"+property+columns);
- if (null != columns)
- if (property.isAnnotationPresent(Comment.class)) {
- String comment = property.getAnnotation(Comment.class).value();
- for (Ejb3Column column : columns) {
- column.getMappingColumn().setComment(comment);
- }
- }
- }
- public static void bindColumnComment(XProperty property, Ejb3Column column) {
- //System.out.println("处理字段注释");
- if (null != column)
- if (property.isAnnotationPresent(Comment.class)) {
- String comment = property.getAnnotation(Comment.class).value();
- column.getMappingColumn().setComment(comment);
- }
- }
- }
下面这个类路径不能变、覆盖hibernate对应的源码。
- /*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301 USA
- */
- package org.hibernate.cfg;
- import java.lang.annotation.Annotation;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.EnumSet;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- import java.util.Set;
- import javax.persistence.Basic;
- import javax.persistence.Cacheable;
- import javax.persistence.CollectionTable;
- import javax.persistence.Column;
- import javax.persistence.DiscriminatorType;
- import javax.persistence.DiscriminatorValue;
- import javax.persistence.ElementCollection;
- import javax.persistence.Embeddable;
- import javax.persistence.Embedded;
- import javax.persistence.EmbeddedId;
- import javax.persistence.Entity;
- import javax.persistence.FetchType;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.IdClass;
- import javax.persistence.InheritanceType;
- import javax.persistence.JoinColumn;
- import javax.persistence.JoinTable;
- import javax.persistence.ManyToMany;
- import javax.persistence.ManyToOne;
- import javax.persistence.MapKey;
- import javax.persistence.MapKeyColumn;
- import javax.persistence.MapKeyJoinColumn;
- import javax.persistence.MapKeyJoinColumns;
- import javax.persistence.MappedSuperclass;
- import javax.persistence.MapsId;
- import javax.persistence.NamedNativeQueries;
- import javax.persistence.NamedNativeQuery;
- import javax.persistence.NamedQueries;
- import javax.persistence.NamedQuery;
- import javax.persistence.OneToMany;
- import javax.persistence.OneToOne;
- import javax.persistence.OrderColumn;
- import javax.persistence.PrimaryKeyJoinColumn;
- import javax.persistence.PrimaryKeyJoinColumns;
- import javax.persistence.SequenceGenerator;
- import javax.persistence.SharedCacheMode;
- import javax.persistence.SqlResultSetMapping;
- import javax.persistence.SqlResultSetMappings;
- import javax.persistence.Table;
- import javax.persistence.TableGenerator;
- import javax.persistence.UniqueConstraint;
- import javax.persistence.Version;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.hibernate.AnnotationException;
- import org.hibernate.AssertionFailure;
- import org.hibernate.EntityMode;
- import org.hibernate.FetchMode;
- import org.hibernate.MappingException;
- import org.hibernate.annotations.BatchSize;
- import org.hibernate.annotations.Cache;
- import org.hibernate.annotations.CacheConcurrencyStrategy;
- import org.hibernate.annotations.Cascade;
- import org.hibernate.annotations.CascadeType;
- import org.hibernate.annotations.Check;
- import org.hibernate.annotations.CollectionId;
- import org.hibernate.annotations.CollectionOfElements;
- import org.hibernate.annotations.Columns;
- import org.hibernate.annotations.DiscriminatorOptions;
- import org.hibernate.annotations.Fetch;
- import org.hibernate.annotations.FetchProfile;
- import org.hibernate.annotations.FetchProfiles;
- import org.hibernate.annotations.Filter;
- import org.hibernate.annotations.FilterDef;
- import org.hibernate.annotations.FilterDefs;
- import org.hibernate.annotations.Filters;
- import org.hibernate.annotations.ForceDiscriminator;
- import org.hibernate.annotations.ForeignKey;
- import org.hibernate.annotations.Formula;
- import org.hibernate.annotations.GenericGenerator;
- import org.hibernate.annotations.GenericGenerators;
- import org.hibernate.annotations.Index;
- import org.hibernate.annotations.LazyToOne;
- import org.hibernate.annotations.LazyToOneOption;
- import org.hibernate.annotations.ManyToAny;
- import org.hibernate.annotations.MapKeyType;
- import org.hibernate.annotations.NaturalId;
- import org.hibernate.annotations.NotFound;
- import org.hibernate.annotations.NotFoundAction;
- import org.hibernate.annotations.OnDelete;
- import org.hibernate.annotations.OnDeleteAction;
- import org.hibernate.annotations.OrderBy;
- import org.hibernate.annotations.ParamDef;
- import org.hibernate.annotations.Parameter;
- import org.hibernate.annotations.Parent;
- import org.hibernate.annotations.Proxy;
- import org.hibernate.annotations.Sort;
- import org.hibernate.annotations.Source;
- import org.hibernate.annotations.Tuplizer;
- import org.hibernate.annotations.Tuplizers;
- import org.hibernate.annotations.TypeDef;
- import org.hibernate.annotations.TypeDefs;
- import org.hibernate.annotations.Where;
- import org.hibernate.annotations.common.reflection.ReflectionManager;
- import org.hibernate.annotations.common.reflection.XAnnotatedElement;
- import org.hibernate.annotations.common.reflection.XClass;
- import org.hibernate.annotations.common.reflection.XMethod;
- import org.hibernate.annotations.common.reflection.XPackage;
- import org.hibernate.annotations.common.reflection.XProperty;
- import org.hibernate.cache.RegionFactory;
- import org.hibernate.cfg.annotations.CollectionBinder;
- import org.hibernate.cfg.annotations.EntityBinder;
- import org.hibernate.cfg.annotations.MapKeyColumnDelegator;
- import org.hibernate.cfg.annotations.MapKeyJoinColumnDelegator;
- import org.hibernate.cfg.annotations.Nullability;
- import org.hibernate.cfg.annotations.PropertyBinder;
- import org.hibernate.cfg.annotations.QueryBinder;
- import org.hibernate.cfg.annotations.SimpleValueBinder;
- import org.hibernate.cfg.annotations.TableBinder;
- import org.hibernate.engine.FilterDefinition;
- import org.hibernate.engine.Versioning;
- import org.hibernate.id.MultipleHiLoPerTableGenerator;
- import org.hibernate.id.PersistentIdentifierGenerator;
- import org.hibernate.id.SequenceHiLoGenerator;
- import org.hibernate.id.TableHiLoGenerator;
- import org.hibernate.id.enhanced.SequenceStyleGenerator;
- import org.hibernate.mapping.Any;
- import org.hibernate.mapping.Component;
- import org.hibernate.mapping.DependantValue;
- import org.hibernate.mapping.IdGenerator;
- import org.hibernate.mapping.Join;
- import org.hibernate.mapping.JoinedSubclass;
- import org.hibernate.mapping.KeyValue;
- import org.hibernate.mapping.PersistentClass;
- import org.hibernate.mapping.Property;
- import org.hibernate.mapping.RootClass;
- import org.hibernate.mapping.SimpleValue;
- import org.hibernate.mapping.SingleTableSubclass;
- import org.hibernate.mapping.Subclass;
- import org.hibernate.mapping.ToOne;
- import org.hibernate.mapping.UnionSubclass;
- import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
- import org.hibernate.persister.entity.SingleTableEntityPersister;
- import org.hibernate.persister.entity.UnionSubclassEntityPersister;
- /**
- * JSR 175 annotation binder which reads the annotations from classes, applies the
- * principles of the EJB3 spec and produces the Hibernate configuration-time metamodel
- * (the classes in the {@code org.hibernate.mapping} package)
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
- @SuppressWarnings("unchecked")
- public final class AnnotationBinder {
- /*
- * Some design description
- * I tried to remove any link to annotation except from the 2 first level of
- * method call.
- * It'll enable to:
- * - facilitate annotation overriding
- * - mutualize one day xml and annotation binder (probably a dream though)
- * - split this huge class in smaller mapping oriented classes
- *
- * bindSomething usually create the mapping container and is accessed by one of the 2 first level method
- * makeSomething usually create the mapping container and is accessed by bindSomething[else]
- * fillSomething take the container into parameter and fill it.
- */
- private AnnotationBinder() {
- }
- private static final Logger log = LoggerFactory.getLogger( AnnotationBinder.class );
- public static void bindDefaults(Mappings mappings) {
- Map defaults = mappings.getReflectionManager().getDefaults();
- {
- List<SequenceGenerator> anns = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );
- if ( anns != null ) {
- for ( SequenceGenerator ann : anns ) {
- IdGenerator idGen = buildIdGenerator( ann, mappings );
- if ( idGen != null ) {
- mappings.addDefaultGenerator( idGen );
- }
- }
- }
- }
- {
- List<TableGenerator> anns = ( List<TableGenerator> ) defaults.get( TableGenerator.class );
- if ( anns != null ) {
- for ( TableGenerator ann : anns ) {
- IdGenerator idGen = buildIdGenerator( ann, mappings );
- if ( idGen != null ) {
- mappings.addDefaultGenerator( idGen );
- }
- }
- }
- }
- {
- List<NamedQuery> anns = ( List<NamedQuery> ) defaults.get( NamedQuery.class );
- if ( anns != null ) {
- for ( NamedQuery ann : anns ) {
- QueryBinder.bindQuery( ann, mappings, true );
- }
- }
- }
- {
- List<NamedNativeQuery> anns = ( List<NamedNativeQuery> ) defaults.get( NamedNativeQuery.class );
- if ( anns != null ) {
- for ( NamedNativeQuery ann : anns ) {
- QueryBinder.bindNativeQuery( ann, mappings, true );
- }
- }
- }
- {
- List<SqlResultSetMapping> anns = ( List<SqlResultSetMapping> ) defaults.get( SqlResultSetMapping.class );
- if ( anns != null ) {
- for ( SqlResultSetMapping ann : anns ) {
- QueryBinder.bindSqlResultsetMapping( ann, mappings, true );
- }
- }
- }
- }
- public static void bindPackage(String packageName, Mappings mappings) {
- XPackage pckg;
- try {
- pckg = mappings.getReflectionManager().packageForName( packageName );
- }
- catch ( ClassNotFoundException cnf ) {
- log.warn( "Package not found or wo package-info.java: {}", packageName );
- return;
- }
- if ( pckg.isAnnotationPresent( SequenceGenerator.class ) ) {
- SequenceGenerator ann = pckg.getAnnotation( SequenceGenerator.class );
- IdGenerator idGen = buildIdGenerator( ann, mappings );
- mappings.addGenerator( idGen );
- log.trace( "Add sequence generator with name: {}", idGen.getName() );
- }
- if ( pckg.isAnnotationPresent( TableGenerator.class ) ) {
- TableGenerator ann = pckg.getAnnotation( TableGenerator.class );
- IdGenerator idGen = buildIdGenerator( ann, mappings );
- mappings.addGenerator( idGen );
- }
- bindGenericGenerators( pckg, mappings );
- bindQueries( pckg, mappings );
- bindFilterDefs( pckg, mappings );
- bindTypeDefs( pckg, mappings );
- bindFetchProfiles( pckg, mappings );
- BinderHelper.bindAnyMetaDefs( pckg, mappings );
- }
- private static void bindGenericGenerators(XAnnotatedElement annotatedElement, Mappings mappings) {
- GenericGenerator defAnn = annotatedElement.getAnnotation( GenericGenerator.class );
- GenericGenerators defsAnn = annotatedElement.getAnnotation( GenericGenerators.class );
- if ( defAnn != null ) {
- bindGenericGenerator( defAnn, mappings );
- }
- if ( defsAnn != null ) {
- for ( GenericGenerator def : defsAnn.value() ) {
- bindGenericGenerator( def, mappings );
- }
- }
- }
- private static void bindGenericGenerator(GenericGenerator def, Mappings mappings) {
- IdGenerator idGen = buildIdGenerator( def, mappings );
- mappings.addGenerator( idGen );
- }
- private static void bindQueries(XAnnotatedElement annotatedElement, Mappings mappings) {
- {
- SqlResultSetMapping ann = annotatedElement.getAnnotation( SqlResultSetMapping.class );
- QueryBinder.bindSqlResultsetMapping( ann, mappings, false );
- }
- {
- SqlResultSetMappings ann = annotatedElement.getAnnotation( SqlResultSetMappings.class );
- if ( ann != null ) {
- for ( SqlResultSetMapping current : ann.value() ) {
- QueryBinder.bindSqlResultsetMapping( current, mappings, false );
- }
- }
- }
- {
- NamedQuery ann = annotatedElement.getAnnotation( NamedQuery.class );
- QueryBinder.bindQuery( ann, mappings, false );
- }
- {
- org.hibernate.annotations.NamedQuery ann = annotatedElement.getAnnotation(
- org.hibernate.annotations.NamedQuery.class
- );
- QueryBinder.bindQuery( ann, mappings );
- }
- {
- NamedQueries ann = annotatedElement.getAnnotation( NamedQueries.class );
- QueryBinder.bindQueries( ann, mappings, false );
- }
- {
- org.hibernate.annotations.NamedQueries ann = annotatedElement.getAnnotation(
- org.hibernate.annotations.NamedQueries.class
- );
- QueryBinder.bindQueries( ann, mappings );
- }
- {
- NamedNativeQuery ann = annotatedElement.getAnnotation( NamedNativeQuery.class );
- QueryBinder.bindNativeQuery( ann, mappings, false );
- }
- {
- org.hibernate.annotations.NamedNativeQuery ann = annotatedElement.getAnnotation(
- org.hibernate.annotations.NamedNativeQuery.class
- );
- QueryBinder.bindNativeQuery( ann, mappings );
- }
- {
- NamedNativeQueries ann = annotatedElement.getAnnotation( NamedNativeQueries.class );
- QueryBinder.bindNativeQueries( ann, mappings, false );
- }
- {
- org.hibernate.annotations.NamedNativeQueries ann = annotatedElement.getAnnotation(
- org.hibernate.annotations.NamedNativeQueries.class
- );
- QueryBinder.bindNativeQueries( ann, mappings );
- }
- }
- private static IdGenerator buildIdGenerator(java.lang.annotation.Annotation ann, Mappings mappings) {
- IdGenerator idGen = new IdGenerator();
- if ( mappings.getSchemaName() != null ) {
- idGen.addParam( PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName() );
- }
- if ( mappings.getCatalogName() != null ) {
- idGen.addParam( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() );
- }
- final boolean useNewGeneratorMappings = mappings.useNewGeneratorMappings();
- if ( ann == null ) {
- idGen = null;
- }
- else if ( ann instanceof TableGenerator ) {
- TableGenerator tabGen = ( TableGenerator ) ann;
- idGen.setName( tabGen.name() );
- if ( useNewGeneratorMappings ) {
- idGen.setIdentifierGeneratorStrategy( org.hibernate.id.enhanced.TableGenerator.class.getName() );
- idGen.addParam( org.hibernate.id.enhanced.TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" );
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.catalog() ) ) {
- idGen.addParam( org.hibernate.id.enhanced.TableGenerator.CATALOG, tabGen.catalog() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.schema() ) ) {
- idGen.addParam( org.hibernate.id.enhanced.TableGenerator.SCHEMA, tabGen.schema() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.table() ) ) {
- idGen.addParam( org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM, tabGen.table() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnName() ) ) {
- idGen.addParam(
- org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM, tabGen.pkColumnName()
- );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnValue() ) ) {
- idGen.addParam(
- org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM, tabGen.pkColumnValue()
- );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.valueColumnName() ) ) {
- idGen.addParam(
- org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM, tabGen.valueColumnName()
- );
- }
- idGen.addParam(
- org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM,
- String.valueOf( tabGen.allocationSize() )
- );
- // See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1
- idGen.addParam(
- org.hibernate.id.enhanced.TableGenerator.INITIAL_PARAM,
- String.valueOf( tabGen.initialValue() + 1 )
- );
- if ( tabGen.uniqueConstraints() != null && tabGen.uniqueConstraints().length > 0 ) {
- log.warn( "Ignoring unique constraints specified on table generator [{}]", tabGen.name() );
- }
- }
- else {
- idGen.setIdentifierGeneratorStrategy( MultipleHiLoPerTableGenerator.class.getName() );
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.table() ) ) {
- idGen.addParam( MultipleHiLoPerTableGenerator.ID_TABLE, tabGen.table() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.catalog() ) ) {
- idGen.addParam( MultipleHiLoPerTableGenerator.CATALOG, tabGen.catalog() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.schema() ) ) {
- idGen.addParam( MultipleHiLoPerTableGenerator.SCHEMA, tabGen.schema() );
- }
- //FIXME implement uniqueconstrains
- if ( tabGen.uniqueConstraints() != null && tabGen.uniqueConstraints().length > 0 ) {
- log.warn( "Ignoring unique constraints specified on table generator [{}]", tabGen.name() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnName() ) ) {
- idGen.addParam( MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, tabGen.pkColumnName() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.valueColumnName() ) ) {
- idGen.addParam( MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, tabGen.valueColumnName() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tabGen.pkColumnValue() ) ) {
- idGen.addParam( MultipleHiLoPerTableGenerator.PK_VALUE_NAME, tabGen.pkColumnValue() );
- }
- idGen.addParam( TableHiLoGenerator.MAX_LO, String.valueOf( tabGen.allocationSize() - 1 ) );
- }
- log.trace( "Add table generator with name: {}", idGen.getName() );
- }
- else if ( ann instanceof SequenceGenerator ) {
- SequenceGenerator seqGen = ( SequenceGenerator ) ann;
- idGen.setName( seqGen.name() );
- if ( useNewGeneratorMappings ) {
- idGen.setIdentifierGeneratorStrategy( SequenceStyleGenerator.class.getName() );
- if ( !BinderHelper.isEmptyAnnotationValue( seqGen.catalog() ) ) {
- idGen.addParam( SequenceStyleGenerator.CATALOG, seqGen.catalog() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( seqGen.schema() ) ) {
- idGen.addParam( SequenceStyleGenerator.SCHEMA, seqGen.schema() );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( seqGen.sequenceName() ) ) {
- idGen.addParam( SequenceStyleGenerator.SEQUENCE_PARAM, seqGen.sequenceName() );
- }
- idGen.addParam( SequenceStyleGenerator.INCREMENT_PARAM, String.valueOf( seqGen.allocationSize() ) );
- idGen.addParam( SequenceStyleGenerator.INITIAL_PARAM, String.valueOf( seqGen.initialValue() ) );
- }
- else {
- idGen.setIdentifierGeneratorStrategy( "seqhilo" );
- if ( !BinderHelper.isEmptyAnnotationValue( seqGen.sequenceName() ) ) {
- idGen.addParam( org.hibernate.id.SequenceGenerator.SEQUENCE, seqGen.sequenceName() );
- }
- //FIXME: work on initialValue() through SequenceGenerator.PARAMETERS
- // steve : or just use o.h.id.enhanced.SequenceStyleGenerator
- if ( seqGen.initialValue() != 1 ) {
- log.warn(
- "Hibernate does not support SequenceGenerator.initialValue() unless '{}' set",
- Configuration.USE_NEW_ID_GENERATOR_MAPPINGS
- );
- }
- idGen.addParam( SequenceHiLoGenerator.MAX_LO, String.valueOf( seqGen.allocationSize() - 1 ) );
- log.trace( "Add sequence generator with name: {}", idGen.getName() );
- }
- }
- else if ( ann instanceof GenericGenerator ) {
- GenericGenerator genGen = ( GenericGenerator ) ann;
- idGen.setName( genGen.name() );
- idGen.setIdentifierGeneratorStrategy( genGen.strategy() );
- Parameter[] params = genGen.parameters();
- for ( Parameter parameter : params ) {
- idGen.addParam( parameter.name(), parameter.value() );
- }
- log.trace( "Add generic generator with name: {}", idGen.getName() );
- }
- else {
- throw new AssertionFailure( "Unknown Generator annotation: " + ann );
- }
- return idGen;
- }
- /**
- * Bind a class having JSR175 annotations. Subclasses <b>have to</b> be bound after its parent class.
- *
- * @param clazzToProcess entity to bind as {@code XClass} instance
- * @param inheritanceStatePerClass Meta data about the inheritance relationships for all mapped classes
- * @param mappings Mapping meta data
- *
- * @throws MappingException in case there is an configuration error
- */
- public static void bindClass(
- XClass clazzToProcess,
- Map<XClass, InheritanceState> inheritanceStatePerClass,
- Mappings mappings) throws MappingException {
- //@Entity and @MappedSuperclass on the same class leads to a NPE down the road
- if ( clazzToProcess.isAnnotationPresent( Entity.class )
- && clazzToProcess.isAnnotationPresent( MappedSuperclass.class ) ) {
- throw new AnnotationException( "An entity cannot be annotated with both @Entity and @MappedSuperclass: "
- + clazzToProcess.getName() );
- }
- //TODO: be more strict with secondarytable allowance (not for ids, not for secondary table join columns etc)
- InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
- AnnotatedClassType classType = mappings.getClassType( clazzToProcess );
- //Queries declared in MappedSuperclass should be usable in Subclasses
- if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) ) {
- bindQueries( clazzToProcess, mappings );
- bindTypeDefs( clazzToProcess, mappings );
- bindFilterDefs( clazzToProcess, mappings );
- }
- if ( !isEntityClassType( clazzToProcess, classType ) ) {
- return;
- }
- log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() );
- PersistentClass superEntity = getSuperEntity(
- clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState
- );
- PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
- Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );
- org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(
- org.hibernate.annotations.Entity.class
- );
- EntityBinder entityBinder = new EntityBinder(
- entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings
- );
- entityBinder.setInheritanceState( inheritanceState );
- bindQueries( clazzToProcess, mappings );
- bindFilterDefs( clazzToProcess, mappings );
- bindTypeDefs( clazzToProcess, mappings );
- bindFetchProfiles( clazzToProcess, mappings );
- BinderHelper.bindAnyMetaDefs( clazzToProcess, mappings );
- String schema = "";
- String table = ""; //might be no @Table annotation on the annotated class
- String catalog = "";
- List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
- if ( clazzToProcess.isAnnotationPresent( javax.persistence.Table.class ) ) {
- javax.persistence.Table tabAnn = clazzToProcess.getAnnotation( javax.persistence.Table.class );
- table = tabAnn.name();
- schema = tabAnn.schema();
- catalog = tabAnn.catalog();
- uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );
- }
- Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
- clazzToProcess, mappings, inheritanceState, superEntity
- );
- Ejb3DiscriminatorColumn discriminatorColumn = null;
- if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
- discriminatorColumn = processDiscriminatorProperties(
- clazzToProcess, mappings, inheritanceState, entityBinder
- );
- }
- entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
- entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
- entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
- entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );
- //Filters are not allowed on subclasses
- if ( !inheritanceState.hasParents() ) {
- bindFilters( clazzToProcess, entityBinder, mappings );
- }
- entityBinder.bindEntity();
- if ( inheritanceState.hasTable() ) {
- Check checkAnn = clazzToProcess.getAnnotation( Check.class );
- String constraints = checkAnn == null ?
- null :
- checkAnn.constraints();
- entityBinder.bindTable(
- schema, catalog, table, uniqueConstraints,
- constraints, inheritanceState.hasDenormalizedTable() ?
- superEntity.getTable() :
- null
- );
- }
- else {
- if ( clazzToProcess.isAnnotationPresent( Table.class ) ) {
- log.warn(
- "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess
- .getName()
- );
- }
- }
- PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
- clazzToProcess,
- persistentClass,
- entityBinder, mappings, inheritanceStatePerClass
- );
- javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation(
- javax.persistence.SecondaryTable.class
- );
- javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation(
- javax.persistence.SecondaryTables.class
- );
- entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn );
- OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );
- boolean onDeleteAppropriate = false;
- if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) {
- onDeleteAppropriate = true;
- final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass;
- if ( persistentClass.getEntityPersisterClass() == null ) {
- persistentClass.getRootClass().setEntityPersisterClass( JoinedSubclassEntityPersister.class );
- }
- SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() );
- jsc.setKey( key );
- ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class );
- if ( fk != null && !BinderHelper.isEmptyAnnotationValue( fk.name() ) ) {
- key.setForeignKeyName( fk.name() );
- }
- if ( onDeleteAnn != null ) {
- key.setCascadeDeleteEnabled( OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) );
- }
- else {
- key.setCascadeDeleteEnabled( false );
- }
- //we are never in a second pass at that stage, so queue it
- SecondPass sp = new JoinedSubclassFkSecondPass( jsc, inheritanceJoinedColumns, key, mappings );
- mappings.addSecondPass( sp );
- mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
- }
- else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
- if ( inheritanceState.hasParents() ) {
- if ( persistentClass.getEntityPersisterClass() == null ) {
- persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class );
- }
- }
- else {
- if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) {
- //need a discriminator column
- bindDiscriminatorToPersistentClass(
- ( RootClass ) persistentClass,
- discriminatorColumn,
- entityBinder.getSecondaryTables(),
- propertyHolder,
- mappings
- );
- entityBinder.bindDiscriminatorValue();//bind it again since the type might have changed
- }
- }
- }
- else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
- if ( inheritanceState.hasParents() ) {
- if ( persistentClass.getEntityPersisterClass() == null ) {
- persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class );
- }
- }
- }
- if ( onDeleteAnn != null && !onDeleteAppropriate ) {
- log.warn(
- "Inapropriate use of @OnDelete on entity, annotation ignored: {}", propertyHolder.getEntityName()
- );
- }
- // try to find class level generators
- HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
- // check properties
- final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState.getElementsToProcess();
- inheritanceState.postProcess( persistentClass, entityBinder );
- final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE
- && inheritanceState.hasParents();
- Set<String> idPropertiesIfIdClass = new HashSet<String>();
- boolean isIdClass = mapAsIdClass(
- inheritanceStatePerClass,
- inheritanceState,
- persistentClass,
- entityBinder,
- propertyHolder,
- elementsToProcess,
- idPropertiesIfIdClass,
- mappings
- );
- if ( !isIdClass ) {
- entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );
- }
- processIdPropertiesIfNotAlready(
- inheritanceStatePerClass,
- mappings,
- persistentClass,
- entityBinder,
- propertyHolder,
- classGenerators,
- elementsToProcess,
- subclassAndSingleTableStrategy,
- idPropertiesIfIdClass
- );
- if ( !inheritanceState.hasParents() ) {
- final RootClass rootClass = ( RootClass ) persistentClass;
- mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
- }
- else {
- superEntity.addSubclass( ( Subclass ) persistentClass );
- }
- mappings.addClass( persistentClass );
- //Process secondary tables and complementary definitions (ie o.h.a.Table)
- mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );
- //add process complementary Table definition (index & all)
- entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
- entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
- CommentBinder.bindTableComment(clazzToProcess, persistentClass);//绑定表名注释
- }
- // parse everything discriminator column relevant in case of single table inheritance
- private static Ejb3DiscriminatorColumn processDiscriminatorProperties(XClass clazzToProcess, Mappings mappings, InheritanceState inheritanceState, EntityBinder entityBinder) {
- Ejb3DiscriminatorColumn discriminatorColumn = null;
- javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
- javax.persistence.DiscriminatorColumn.class
- );
- DiscriminatorType discriminatorType = discAnn != null ?
- discAnn.discriminatorType() :
- DiscriminatorType.STRING;
- org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
- org.hibernate.annotations.DiscriminatorFormula.class
- );
- if ( !inheritanceState.hasParents() ) {
- discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
- discriminatorType, discAnn, discFormulaAnn, mappings
- );
- }
- if ( discAnn != null && inheritanceState.hasParents() ) {
- log.warn(
- "Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
- clazzToProcess.getName()
- );
- }
- String discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
- clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
- null;
- entityBinder.setDiscriminatorValue( discrimValue );
- if ( clazzToProcess.isAnnotationPresent( ForceDiscriminator.class ) ) {
- log.warn( "@ForceDiscriminator is deprecated use @DiscriminatorOptions instead." );
- entityBinder.setForceDiscriminator( true );
- }
- DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
- if ( discriminatorOptions != null) {
- entityBinder.setForceDiscriminator( discriminatorOptions.force() );
- entityBinder.setInsertableDiscriminator( discriminatorOptions.insert() );
- }
- return discriminatorColumn;
- }
- private static void processIdPropertiesIfNotAlready(
- Map<XClass, InheritanceState> inheritanceStatePerClass,
- Mappings mappings,
- PersistentClass persistentClass,
- EntityBinder entityBinder,
- PropertyHolder propertyHolder,
- HashMap<String, IdGenerator> classGenerators,
- InheritanceState.ElementsToProcess elementsToProcess,
- boolean subclassAndSingleTableStrategy,
- Set<String> idPropertiesIfIdClass) {
- Set<String> missingIdProperties = new HashSet<String>( idPropertiesIfIdClass );
- for ( PropertyData propertyAnnotatedElement : elementsToProcess.getElements() ) {
- String propertyName = propertyAnnotatedElement.getPropertyName();
- if ( !idPropertiesIfIdClass.contains( propertyName ) ) {
- processElementAnnotations(
- propertyHolder,
- subclassAndSingleTableStrategy ?
- Nullability.FORCED_NULL :
- Nullability.NO_CONSTRAINT,
- propertyAnnotatedElement, classGenerators, entityBinder,
- false, false, false, mappings, inheritanceStatePerClass
- );
- }
- else {
- missingIdProperties.remove( propertyName );
- }
- }
- if ( missingIdProperties.size() != 0 ) {
- StringBuilder missings = new StringBuilder();
- for ( String property : missingIdProperties ) {
- missings.append( property ).append( ", " );
- }
- throw new AnnotationException(
- "Unable to find properties ("
- + missings.substring( 0, missings.length() - 2 )
- + ") in entity annotated with @IdClass:" + persistentClass.getEntityName()
- );
- }
- }
- private static boolean mapAsIdClass(
- Map<XClass, InheritanceState> inheritanceStatePerClass,
- InheritanceState inheritanceState,
- PersistentClass persistentClass,
- EntityBinder entityBinder,
- PropertyHolder propertyHolder,
- InheritanceState.ElementsToProcess elementsToProcess,
- Set<String> idPropertiesIfIdClass,
- Mappings mappings) {
- /*
- * We are looking for @IdClass
- * In general we map the id class as identifier using the mapping metadata of the main entity's properties
- * and we create an identifier mapper containing the id properties of the main entity
- *
- * In JPA 2, there is a shortcut if the id class is the Pk of the associated class pointed to by the id
- * it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way
- */
- XClass classWithIdClass = inheritanceState.getClassWithIdClass( false );
- if ( classWithIdClass != null ) {
- IdClass idClass = classWithIdClass.getAnnotation( IdClass.class );
- XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
- PropertyData inferredData = new PropertyPreloadedData(
- entityBinder.getPropertyAccessType(), "id", compositeClass
- );
- PropertyData baseInferredData = new PropertyPreloadedData(
- entityBinder.getPropertyAccessType(), "id", classWithIdClass
- );
- AccessType propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
- //In JPA 2, there is a shortcut if the IdClass is the Pk of the associated class pointed to by the id
- //it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way
- final boolean isFakeIdClass = isIdClassPkOfTheAssociatedEntity(
- elementsToProcess,
- compositeClass,
- inferredData,
- baseInferredData,
- propertyAccessor,
- inheritanceStatePerClass,
- mappings
- );
- if ( isFakeIdClass ) {
- return false;
- }
- boolean isComponent = true;
- String generatorType = "assigned";
- String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
- boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();
- entityBinder.setIgnoreIdAnnotations( true );
- propertyHolder.setInIdClass( true );
- bindIdClass(
- generatorType,
- generator,
- inferredData,
- baseInferredData,
- null,
- propertyHolder,
- isComponent,
- propertyAccessor,
- entityBinder,
- true,
- false,
- mappings,
- inheritanceStatePerClass
- );
- propertyHolder.setInIdClass( null );
- inferredData = new PropertyPreloadedData(
- propertyAccessor, "_identifierMapper", compositeClass
- );
- Component mapper = fillComponent(
- propertyHolder,
- inferredData,
- baseInferredData,
- propertyAccessor,
- false,
- entityBinder,
- true,
- true,
- false,
- mappings,
- inheritanceStatePerClass
- );
- entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
- persistentClass.setIdentifierMapper( mapper );
- //If id definition is on a mapped superclass, update the mapping
- final org.hibernate.mapping.MappedSuperclass superclass =
- BinderHelper.getMappedSuperclassOrNull(
- inferredData.getDeclaringClass(),
- inheritanceStatePerClass,
- mappings
- );
- if ( superclass != null ) {
- superclass.setDeclaredIdentifierMapper( mapper );
- }
- else {
- //we are for sure on the entity
- persistentClass.setDeclaredIdentifierMapper( mapper );
- }
- Property property = new Property();
- property.setName( "_identifierMapper" );
- property.setNodeName( "id" );
- property.setUpdateable( false );
- property.setInsertable( false );
- property.setValue( mapper );
- property.setPropertyAccessorName( "embedded" );
- persistentClass.addProperty( property );
- entityBinder.setIgnoreIdAnnotations( true );
- Iterator properties = mapper.getPropertyIterator();
- while ( properties.hasNext() ) {
- idPropertiesIfIdClass.add( ( ( Property ) properties.next() ).getName() );
- }
- return true;
- }
- else {
- return false;
- }
- }
- private static boolean isIdClassPkOfTheAssociatedEntity(
- InheritanceState.ElementsToProcess elementsToProcess,
- XClass compositeClass,
- PropertyData inferredData,
- PropertyData baseInferredData,
- AccessType propertyAccessor,
- Map<XClass, InheritanceState> inheritanceStatePerClass,
- Mappings mappings) {
- if ( elementsToProcess.getIdPropertyCount() == 1 ) {
- final PropertyData idPropertyOnBaseClass = getUniqueIdPropertyFromBaseClass(
- inferredData, baseInferredData, propertyAccessor, mappings
- );
- final InheritanceState state = inheritanceStatePerClass.get( idPropertyOnBaseClass.getClassOrElement() );
- if ( state == null ) {
- return false; //while it is likely a user error, let's consider it is something that might happen
- }
- final XClass associatedClassWithIdClass = state.getClassWithIdClass( true );
- if ( associatedClassWithIdClass == null ) {
- //we cannot know for sure here unless we try and find the @EmbeddedId
- //Let's not do this thorough checking but do some extra validation
- final XProperty property = idPropertyOnBaseClass.getProperty();
- return property.isAnnotationPresent( ManyToOne.class )
- || property.isAnnotationPresent( OneToOne.class );
- }
- else {
- final XClass idClass = mappings.getReflectionManager().toXClass(
- associatedClassWithIdClass.getAnnotation( IdClass.class ).value()
- );
- return idClass.equals( compositeClass );
- }
- }
- else {
- return false;
- }
- }
- private static Cache determineCacheSettings(XClass clazzToProcess, Mappings mappings) {
- Cache cacheAnn = clazzToProcess.getAnnotation( Cache.class );
- if ( cacheAnn != null ) {
- return cacheAnn;
- }
- Cacheable cacheableAnn = clazzToProcess.getAnnotation( Cacheable.class );
- SharedCacheMode mode = determineSharedCacheMode( mappings );
- switch ( mode ) {
- case ALL: {
- cacheAnn = buildCacheMock( clazzToProcess.getName(), mappings );
- break;
- }
- case ENABLE_SELECTIVE: {
- if ( cacheableAnn != null && cacheableAnn.value() ) {
- cacheAnn = buildCacheMock( clazzToProcess.getName(), mappings );
- }
- break;
- }
- case DISABLE_SELECTIVE: {
- if ( cacheableAnn == null || cacheableAnn.value() ) {
- cacheAnn = buildCacheMock( clazzToProcess.getName(), mappings );
- }
- break;
- }
- default: {
- // treat both NONE and UNSPECIFIED the same
- break;
- }
- }
- return cacheAnn;
- }
- private static SharedCacheMode determineSharedCacheMode(Mappings mappings) {
- SharedCacheMode mode;
- final Object value = mappings.getConfigurationProperties().get( "javax.persistence.sharedCache.mode" );
- if ( value == null ) {
- log.debug( "no value specified for 'javax.persistence.sharedCache.mode'; using UNSPECIFIED" );
- mode = SharedCacheMode.UNSPECIFIED;
- }
- else {
- if ( SharedCacheMode.class.isInstance( value ) ) {
- mode = ( SharedCacheMode ) value;
- }
- else {
- try {
- mode = SharedCacheMode.valueOf( value.toString() );
- }
- catch ( Exception e ) {
- log.debug(
- "Unable to resolve given mode name [" + value.toString()
- + "]; using UNSPECIFIED : " + e.toString()
- );
- mode = SharedCacheMode.UNSPECIFIED;
- }
- }
- }
- return mode;
- }
- private static Cache buildCacheMock(String region, Mappings mappings) {
- return new LocalCacheAnnotationImpl( region, determineCacheConcurrencyStrategy( mappings ) );
- }
- private static CacheConcurrencyStrategy DEFAULT_CACHE_CONCURRENCY_STRATEGY;
- static void prepareDefaultCacheConcurrencyStrategy(Properties properties) {
- if ( DEFAULT_CACHE_CONCURRENCY_STRATEGY != null ) {
- log.trace( "Default cache concurrency strategy already defined" );
- return;
- }
- if ( !properties.containsKey( Configuration.DEFAULT_CACHE_CONCURRENCY_STRATEGY ) ) {
- log.trace( "Given properties did not contain any default cache concurrency strategy setting" );
- return;
- }
- final String strategyName = properties.getProperty( Configuration.DEFAULT_CACHE_CONCURRENCY_STRATEGY );
- log.trace( "Discovered default cache concurrency strategy via config [" + strategyName + "]" );
- CacheConcurrencyStrategy strategy = CacheConcurrencyStrategy.parse( strategyName );
- if ( strategy == null ) {
- log.trace( "Discovered default cache concurrency strategy specified nothing" );
- return;
- }
- log.debug( "Setting default cache concurrency strategy via config [" + strategy.name() + "]" );
- DEFAULT_CACHE_CONCURRENCY_STRATEGY = strategy;
- }
- private static CacheConcurrencyStrategy determineCacheConcurrencyStrategy(Mappings mappings) {
- if ( DEFAULT_CACHE_CONCURRENCY_STRATEGY == null ) {
- final RegionFactory cacheRegionFactory = SettingsFactory.createRegionFactory(
- mappings.getConfigurationProperties(), true
- );
- DEFAULT_CACHE_CONCURRENCY_STRATEGY = CacheConcurrencyStrategy.fromAccessType( cacheRegionFactory.getDefaultAccessType() );
- }
- return DEFAULT_CACHE_CONCURRENCY_STRATEGY;
- }
- @SuppressWarnings({ "ClassExplicitlyAnnotation" })
- private static class LocalCacheAnnotationImpl implements Cache {
- private final String region;
- private final CacheConcurrencyStrategy usage;
- private LocalCacheAnnotationImpl(String region, CacheConcurrencyStrategy usage) {
- this.region = region;
- this.usage = usage;
- }
- public CacheConcurrencyStrategy usage() {
- return usage;
- }
- public String region() {
- return region;
- }
- public String include() {
- return "all";
- }
- public Class<? extends Annotation> annotationType() {
- return Cache.class;
- }
- }
- private static PersistentClass makePersistentClass(InheritanceState inheritanceState, PersistentClass superEntity) {
- //we now know what kind of persistent entity it is
- PersistentClass persistentClass;
- //create persistent class
- if ( !inheritanceState.hasParents() ) {
- persistentClass = new RootClass();
- }
- else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
- persistentClass = new SingleTableSubclass( superEntity );
- }
- else if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) ) {
- persistentClass = new JoinedSubclass( superEntity );
- }
- else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
- persistentClass = new UnionSubclass( superEntity );
- }
- else {
- throw new AssertionFailure( "Unknown inheritance type: " + inheritanceState.getType() );
- }
- return persistentClass;
- }
- private static Ejb3JoinColumn[] makeInheritanceJoinColumns(
- XClass clazzToProcess,
- Mappings mappings,
- InheritanceState inheritanceState,
- PersistentClass superEntity) {
- Ejb3JoinColumn[] inheritanceJoinedColumns = null;
- final boolean hasJoinedColumns = inheritanceState.hasParents()
- && InheritanceType.JOINED.equals( inheritanceState.getType() );
- if ( hasJoinedColumns ) {
- //@Inheritance(JOINED) subclass need to link back to the super entity
- PrimaryKeyJoinColumns jcsAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumns.class );
- boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0;
- if ( explicitInheritanceJoinedColumns ) {
- int nbrOfInhJoinedColumns = jcsAnn.value().length;
- PrimaryKeyJoinColumn jcAnn;
- inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns];
- for ( int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++ ) {
- jcAnn = jcsAnn.value()[colIndex];
- inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn(
- jcAnn, null, superEntity.getIdentifier(),
- ( Map<String, Join> ) null, ( PropertyHolder ) null, mappings
- );
- }
- }
- else {
- PrimaryKeyJoinColumn jcAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class );
- inheritanceJoinedColumns = new Ejb3JoinColumn[1];
- inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn(
- jcAnn, null, superEntity.getIdentifier(),
- ( Map<String, Join> ) null, ( PropertyHolder ) null, mappings
- );
- }
- log.trace( "Subclass joined column(s) created" );
- }
- else {
- if ( clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumns.class )
- || clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumn.class ) ) {
- log.warn( "Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored" );
- }
- }
- return inheritanceJoinedColumns;
- }
- private static PersistentClass getSuperEntity(XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, Mappings mappings, InheritanceState inheritanceState) {
- InheritanceState superEntityState = InheritanceState.getInheritanceStateOfSuperEntity(
- clazzToProcess, inheritanceStatePerClass
- );
- PersistentClass superEntity = superEntityState != null ?
- mappings.getClass(
- superEntityState.getClazz().getName()
- ) :
- null;
- if ( superEntity == null ) {
- //check if superclass is not a potential persistent class
- if ( inheritanceState.hasParents() ) {
- throw new AssertionFailure(
- "Subclass has to be binded after it's mother class: "
- + superEntityState.getClazz().getName()
- );
- }
- }
- return superEntity;
- }
- private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassType classType) {
- if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) //will be processed by their subentities
- || AnnotatedClassType.NONE.equals( classType ) //to be ignored
- || AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration
- ) {
- if ( AnnotatedClassType.NONE.equals( classType )
- && clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) {
- log.warn(
- "Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity "
- + "(most likely a user error): {}", clazzToProcess.getName()
- );
- }
- return false;
- }
- if ( !classType.equals( AnnotatedClassType.ENTITY ) ) {
- throw new AnnotationException(
- "Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess
- .getName()
- );
- }
- return true;
- }
- /*
- * Process the filters defined on the given class, as well as all filters defined
- * on the MappedSuperclass(s) in the inheritance hierarchy
- */
- private static void bindFilters(XClass annotatedClass, EntityBinder entityBinder,
- Mappings mappings) {
- bindFilters( annotatedClass, entityBinder );
- XClass classToProcess = annotatedClass.getSuperclass();
- while ( classToProcess != null ) {
- AnnotatedClassType classType = mappings.getClassType( classToProcess );
- if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) ) {
- bindFilters( classToProcess, entityBinder );
- }
- classToProcess = classToProcess.getSuperclass();
- }
- }
- private static void bindFilters(XAnnotatedElement annotatedElement, EntityBinder entityBinder) {
- Filters filtersAnn = annotatedElement.getAnnotation( Filters.class );
- if ( filtersAnn != null ) {
- for ( Filter filter : filtersAnn.value() ) {
- entityBinder.addFilter( filter.name(), filter.condition() );
- }
- }
- Filter filterAnn = annotatedElement.getAnnotation( Filter.class );
- if ( filterAnn != null ) {
- entityBinder.addFilter( filterAnn.name(), filterAnn.condition() );
- }
- }
- private static void bindFilterDefs(XAnnotatedElement annotatedElement, Mappings mappings) {
- FilterDef defAnn = annotatedElement.getAnnotation( FilterDef.class );
- FilterDefs defsAnn = annotatedElement.getAnnotation( FilterDefs.class );
- if ( defAnn != null ) {
- bindFilterDef( defAnn, mappings );
- }
- if ( defsAnn != null ) {
- for ( FilterDef def : defsAnn.value() ) {
- bindFilterDef( def, mappings );
- }
- }
- }
- private static void bindFilterDef(FilterDef defAnn, Mappings mappings) {
- Map<String, org.hibernate.type.Type> params = new HashMap<String, org.hibernate.type.Type>();
- for ( ParamDef param : defAnn.parameters() ) {
- params.put( param.name(), mappings.getTypeResolver().heuristicType( param.type() ) );
- }
- FilterDefinition def = new FilterDefinition( defAnn.name(), defAnn.defaultCondition(), params );
- log.info( "Binding filter definition: {}", def.getFilterName() );
- mappings.addFilterDefinition( def );
- }
- private static void bindTypeDefs(XAnnotatedElement annotatedElement, Mappings mappings) {
- TypeDef defAnn = annotatedElement.getAnnotation( TypeDef.class );
- TypeDefs defsAnn = annotatedElement.getAnnotation( TypeDefs.class );
- if ( defAnn != null ) {
- bindTypeDef( defAnn, mappings );
- }
- if ( defsAnn != null ) {
- for ( TypeDef def : defsAnn.value() ) {
- bindTypeDef( def, mappings );
- }
- }
- }
- private static void bindFetchProfiles(XAnnotatedElement annotatedElement, Mappings mappings) {
- FetchProfile fetchProfileAnnotation = annotatedElement.getAnnotation( FetchProfile.class );
- FetchProfiles fetchProfileAnnotations = annotatedElement.getAnnotation( FetchProfiles.class );
- if ( fetchProfileAnnotation != null ) {
- bindFetchProfile( fetchProfileAnnotation, mappings );
- }
- if ( fetchProfileAnnotations != null ) {
- for ( FetchProfile profile : fetchProfileAnnotations.value() ) {
- bindFetchProfile( profile, mappings );
- }
- }
- }
- private static void bindFetchProfile(FetchProfile fetchProfileAnnotation, Mappings mappings) {
- for ( FetchProfile.FetchOverride fetch : fetchProfileAnnotation.fetchOverrides() ) {
- org.hibernate.annotations.FetchMode mode = fetch.mode();
- if ( !mode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) {
- throw new MappingException( "Only FetchMode.JOIN is currently supported" );
- }
- SecondPass sp = new VerifyFetchProfileReferenceSecondPass( fetchProfileAnnotation.name(), fetch, mappings );
- mappings.addSecondPass( sp );
- }
- }
- private static void bindTypeDef(TypeDef defAnn, Mappings mappings) {
- Properties params = new Properties();
- for ( Parameter param : defAnn.parameters() ) {
- params.setProperty( param.name(), param.value() );
- }
- if ( BinderHelper.isEmptyAnnotationValue( defAnn.name() ) && defAnn.defaultForType().equals( void.class ) ) {
- throw new AnnotationException(
- "Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass " +
- defAnn.typeClass().getName()
- );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( defAnn.name() ) ) {
- log.info( "Binding type definition: {}", defAnn.name() );
- mappings.addTypeDef( defAnn.name(), defAnn.typeClass().getName(), params );
- }
- if ( !defAnn.defaultForType().equals( void.class ) ) {
- log.info( "Binding type definition: {}", defAnn.defaultForType().getName() );
- mappings.addTypeDef( defAnn.defaultForType().getName(), defAnn.typeClass().getName(), params );
- }
- }
- private static void bindDiscriminatorToPersistentClass(
- RootClass rootClass,
- Ejb3DiscriminatorColumn discriminatorColumn,
- Map<String, Join> secondaryTables,
- PropertyHolder propertyHolder,
- Mappings mappings) {
- if ( rootClass.getDiscriminator() == null ) {
- if ( discriminatorColumn == null ) {
- throw new AssertionFailure( "discriminator column should have been built" );
- }
- discriminatorColumn.setJoins( secondaryTables );
- discriminatorColumn.setPropertyHolder( propertyHolder );
- SimpleValue discrim = new SimpleValue( mappings, rootClass.getTable() );
- rootClass.setDiscriminator( discrim );
- discriminatorColumn.linkWithValue( discrim );
- discrim.setTypeName( discriminatorColumn.getDiscriminatorTypeName() );
- rootClass.setPolymorphic( true );
- log.trace( "Setting discriminator for entity {}", rootClass.getEntityName() );
- }
- }
- /**
- * @param elements List of {@code ProperyData} instances
- * @param defaultAccessType The default value access strategy which has to be used in case no explicit local access
- * strategy is used
- * @param propertyContainer Metadata about a class and its properties
- * @param mappings Mapping meta data
- *
- * @return the number of id properties found while iterating the elements of {@code annotatedClass} using
- * the determined access strategy, {@code false} otherwise.
- */
- static int addElementsOfClass(
- List<PropertyData> elements,
- AccessType defaultAccessType,
- PropertyContainer propertyContainer,
- Mappings mappings) {
- int idPropertyCounter = 0;
- AccessType accessType = defaultAccessType;
- if ( propertyContainer.hasExplicitAccessStrategy() ) {
- accessType = propertyContainer.getExplicitAccessStrategy();
- }
- Collection<XProperty> properties = propertyContainer.getProperties( accessType );
- for ( XProperty p : properties ) {
- final int currentIdPropertyCounter = addProperty(
- propertyContainer, p, elements, accessType.getType(), mappings
- );
- idPropertyCounter += currentIdPropertyCounter;
- }
- return idPropertyCounter;
- }
- private static int addProperty(
- PropertyContainer propertyContainer,
- XProperty property,
- List<PropertyData> annElts,
- String propertyAccessor,
- Mappings mappings) {
- final XClass declaringClass = propertyContainer.getDeclaringClass();
- final XClass entity = propertyContainer.getEntityAtStake();
- int idPropertyCounter = 0;
- PropertyData propertyAnnotatedElement = new PropertyInferredData(
- declaringClass, property, propertyAccessor,
- mappings.getReflectionManager()
- );
- /*
- * put element annotated by @Id in front
- * since it has to be parsed before any association by Hibernate
- */
- final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
- if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
- annElts.add( 0, propertyAnnotatedElement );
- /**
- * The property must be put in hibernate.properties as it's a system wide property. Fixable?
- * TODO support true/false/default on the property instead of present / not present
- * TODO is @Column mandatory?
- * TODO add method support
- */
- if ( mappings.isSpecjProprietarySyntaxEnabled() ) {
- if ( element.isAnnotationPresent( Id.class ) && element.isAnnotationPresent( Column.class ) ) {
- String columnName = element.getAnnotation( Column.class ).name();
- for ( XProperty prop : declaringClass.getDeclaredProperties( AccessType.FIELD.getType() ) ) {
- if ( prop.isAnnotationPresent( JoinColumn.class )
- && prop.getAnnotation( JoinColumn.class ).name().equals( columnName )
- && !prop.isAnnotationPresent( MapsId.class ) ) {
- //create a PropertyData fpr the specJ property holding the mapping
- PropertyData specJPropertyData = new PropertyInferredData(
- declaringClass, //same dec
- prop, // the actual @XToOne property
- propertyAccessor, //TODO we should get the right accessor but the same as id would do
- mappings.getReflectionManager()
- );
- mappings.addPropertyAnnotatedWithMapsIdSpecj( entity, specJPropertyData, element.toString() );
- }
- }
- }
- }
- if ( element.isAnnotationPresent( ManyToOne.class ) || element.isAnnotationPresent( OneToOne.class ) ) {
- mappings.addToOneAndIdProperty( entity, propertyAnnotatedElement );
- }
- idPropertyCounter++;
- }
- else {
- annElts.add( propertyAnnotatedElement );
- }
- if ( element.isAnnotationPresent( MapsId.class ) ) {
- mappings.addPropertyAnnotatedWithMapsId( entity, propertyAnnotatedElement );
- }
- return idPropertyCounter;
- }
- /*
- * Process annotation of a particular property
- */
- private static void processElementAnnotations(
- PropertyHolder propertyHolder,
- Nullability nullability,
- PropertyData inferredData,
- HashMap<String, IdGenerator> classGenerators,
- EntityBinder entityBinder,
- boolean isIdentifierMapper,
- boolean isComponentEmbedded,
- boolean inSecondPass,
- Mappings mappings,
- Map<XClass, InheritanceState> inheritanceStatePerClass) throws MappingException {
- /**
- * inSecondPass can only be used to apply right away the second pass of a composite-element
- * Because it's a value type, there is no bidirectional association, hence second pass
- * ordering does not matter
- */
- log.trace(
- "Processing annotations of {}.{}", propertyHolder.getEntityName(), inferredData.getPropertyName()
- );
- final XProperty property = inferredData.getProperty();
- if ( property.isAnnotationPresent( Parent.class ) ) {
- if ( propertyHolder.isComponent() ) {
- propertyHolder.setParentProperty( property.getName() );
- }
- else {
- throw new AnnotationException(
- "@Parent cannot be applied outside an embeddable object: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- return;
- }
- ColumnsBuilder columnsBuilder = new ColumnsBuilder(
- propertyHolder, nullability, property, inferredData, entityBinder, mappings
- ).extractMetadata();
- Ejb3Column[] columns = columnsBuilder.getColumns();
- Ejb3JoinColumn[] joinColumns = columnsBuilder.getJoinColumns();
- final XClass returnedClass = inferredData.getClassOrElement();
- //prepare PropertyBinder
- PropertyBinder propertyBinder = new PropertyBinder();
- propertyBinder.setName( inferredData.getPropertyName() );
- propertyBinder.setReturnedClassName( inferredData.getTypeName() );
- propertyBinder.setAccessType( inferredData.getDefaultAccess() );
- propertyBinder.setHolder( propertyHolder );
- propertyBinder.setProperty( property );
- propertyBinder.setReturnedClass( inferredData.getPropertyClass() );
- propertyBinder.setMappings( mappings );
- if ( isIdentifierMapper ) {
- propertyBinder.setInsertable( false );
- propertyBinder.setUpdatable( false );
- }
- propertyBinder.setDeclaringClass( inferredData.getDeclaringClass() );
- propertyBinder.setEntityBinder( entityBinder );
- propertyBinder.setInheritanceStatePerClass( inheritanceStatePerClass );
- boolean isId = !entityBinder.isIgnoreIdAnnotations() &&
- ( property.isAnnotationPresent( Id.class )
- || property.isAnnotationPresent( EmbeddedId.class ) );
- propertyBinder.setId( isId );
- if ( property.isAnnotationPresent( Version.class ) ) {
- if ( isIdentifierMapper ) {
- throw new AnnotationException(
- "@IdClass class should not have @Version property"
- );
- }
- if ( !( propertyHolder.getPersistentClass() instanceof RootClass ) ) {
- throw new AnnotationException(
- "Unable to define/override @Version on a subclass: "
- + propertyHolder.getEntityName()
- );
- }
- if ( !propertyHolder.isEntity() ) {
- throw new AnnotationException(
- "Unable to define @Version on an embedded class: "
- + propertyHolder.getEntityName()
- );
- }
- log.trace( "{} is a version property", inferredData.getPropertyName() );
- RootClass rootClass = ( RootClass ) propertyHolder.getPersistentClass();
- propertyBinder.setColumns( columns );
- Property prop = propertyBinder.makePropertyValueAndBind();
- setVersionInformation( property, propertyBinder );
- rootClass.setVersion( prop );
- //If version is on a mapped superclass, update the mapping
- final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
- inferredData.getDeclaringClass(),
- inheritanceStatePerClass,
- mappings
- );
- if ( superclass != null ) {
- superclass.setDeclaredVersion( prop );
- }
- else {
- //we know the property is on the actual entity
- rootClass.setDeclaredVersion( prop );
- }
- SimpleValue simpleValue = ( SimpleValue ) prop.getValue();
- simpleValue.setNullValue( "undefined" );
- rootClass.setOptimisticLockMode( Versioning.OPTIMISTIC_LOCK_VERSION );
- log.trace(
- "Version name: {}, unsavedValue: {}", rootClass.getVersion().getName(),
- ( ( SimpleValue ) rootClass.getVersion().getValue() ).getNullValue()
- );
- }
- else {
- final boolean forcePersist = property.isAnnotationPresent( MapsId.class )
- || property.isAnnotationPresent( Id.class );
- if ( property.isAnnotationPresent( ManyToOne.class ) ) {
- ManyToOne ann = property.getAnnotation( ManyToOne.class );
- //check validity
- if ( property.isAnnotationPresent( Column.class )
- || property.isAnnotationPresent( Columns.class ) ) {
- throw new AnnotationException(
- "@Column(s) not allowed on a @ManyToOne property: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- Cascade hibernateCascade = property.getAnnotation( Cascade.class );
- NotFound notFound = property.getAnnotation( NotFound.class );
- boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );
- OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
- boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );
- JoinTable assocTable = propertyHolder.getJoinTable( property );
- if ( assocTable != null ) {
- Join join = propertyHolder.addJoin( assocTable, false );
- for ( Ejb3JoinColumn joinColumn : joinColumns ) {
- joinColumn.setSecondaryTableName( join.getTable().getName() );
- }
- }
- final boolean mandatory = !ann.optional() || forcePersist;
- bindManyToOne(
- getCascadeStrategy( ann.cascade(), hibernateCascade, false, forcePersist ),
- joinColumns,
- !mandatory,
- ignoreNotFound, onDeleteCascade,
- ToOneBinder.getTargetEntity( inferredData, mappings ),
- propertyHolder,
- inferredData, false, isIdentifierMapper,
- inSecondPass, propertyBinder, mappings
- );
- }
- else if ( property.isAnnotationPresent( OneToOne.class ) ) {
- OneToOne ann = property.getAnnotation( OneToOne.class );
- //check validity
- if ( property.isAnnotationPresent( Column.class )
- || property.isAnnotationPresent( Columns.class ) ) {
- throw new AnnotationException(
- "@Column(s) not allowed on a @OneToOne property: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- //FIXME support a proper PKJCs
- boolean trueOneToOne = property.isAnnotationPresent( PrimaryKeyJoinColumn.class )
- || property.isAnnotationPresent( PrimaryKeyJoinColumns.class );
- Cascade hibernateCascade = property.getAnnotation( Cascade.class );
- NotFound notFound = property.getAnnotation( NotFound.class );
- boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );
- OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
- boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );
- JoinTable assocTable = propertyHolder.getJoinTable( property );
- if ( assocTable != null ) {
- Join join = propertyHolder.addJoin( assocTable, false );
- for ( Ejb3JoinColumn joinColumn : joinColumns ) {
- joinColumn.setSecondaryTableName( join.getTable().getName() );
- }
- }
- //MapsId means the columns belong to the pk => not null
- //@PKJC must be constrained
- final boolean mandatory = !ann.optional() || forcePersist || trueOneToOne;
- bindOneToOne(
- getCascadeStrategy( ann.cascade(), hibernateCascade, ann.orphanRemoval(), forcePersist ),
- joinColumns,
- !mandatory,
- getFetchMode( ann.fetch() ),
- ignoreNotFound, onDeleteCascade,
- ToOneBinder.getTargetEntity( inferredData, mappings ),
- propertyHolder,
- inferredData,
- ann.mappedBy(),
- trueOneToOne,
- isIdentifierMapper,
- inSecondPass,
- propertyBinder,
- mappings
- );
- }
- else if ( property.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
- //check validity
- if ( property.isAnnotationPresent( Column.class )
- || property.isAnnotationPresent( Columns.class ) ) {
- throw new AnnotationException(
- "@Column(s) not allowed on a @Any property: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- Cascade hibernateCascade = property.getAnnotation( Cascade.class );
- OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
- boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );
- JoinTable assocTable = propertyHolder.getJoinTable( property );
- if ( assocTable != null ) {
- Join join = propertyHolder.addJoin( assocTable, false );
- for ( Ejb3JoinColumn joinColumn : joinColumns ) {
- joinColumn.setSecondaryTableName( join.getTable().getName() );
- }
- }
- bindAny(
- getCascadeStrategy( null, hibernateCascade, false, forcePersist ),
- //@Any has not cascade attribute
- joinColumns,
- onDeleteCascade,
- nullability,
- propertyHolder,
- inferredData,
- entityBinder,
- isIdentifierMapper,
- mappings
- );
- }
- else if ( property.isAnnotationPresent( OneToMany.class )
- || property.isAnnotationPresent( ManyToMany.class )
- || property.isAnnotationPresent( CollectionOfElements.class ) //legacy Hibernate
- || property.isAnnotationPresent( ElementCollection.class )
- || property.isAnnotationPresent( ManyToAny.class ) ) {
- OneToMany oneToManyAnn = property.getAnnotation( OneToMany.class );
- ManyToMany manyToManyAnn = property.getAnnotation( ManyToMany.class );
- ElementCollection elementCollectionAnn = property.getAnnotation( ElementCollection.class );
- CollectionOfElements collectionOfElementsAnn = property.getAnnotation( CollectionOfElements.class ); //legacy hibernate
- final IndexColumn indexColumn;
- if ( property.isAnnotationPresent( OrderColumn.class ) ) {
- indexColumn = IndexColumn.buildColumnFromAnnotation(
- property.getAnnotation( OrderColumn.class ),
- propertyHolder,
- inferredData,
- entityBinder.getSecondaryTables(),
- mappings
- );
- }
- else {
- //if @IndexColumn is not there, the generated IndexColumn is an implicit column and not used.
- //so we can leave the legacy processing as the default
- indexColumn = IndexColumn.buildColumnFromAnnotation(
- property.getAnnotation( org.hibernate.annotations.IndexColumn.class ),
- propertyHolder,
- inferredData,
- mappings
- );
- }
- CollectionBinder collectionBinder = CollectionBinder.getCollectionBinder(
- propertyHolder.getEntityName(),
- property,
- !indexColumn.isImplicit(),
- property.isAnnotationPresent( CollectionOfElements.class )
- || property.isAnnotationPresent( org.hibernate.annotations.MapKey.class )
- || property.isAnnotationPresent( MapKeyType.class )
- // || property.isAnnotationPresent( ManyToAny.class )
- );
- collectionBinder.setIndexColumn( indexColumn );
- collectionBinder.setMapKey( property.getAnnotation( MapKey.class ) );
- collectionBinder.setPropertyName( inferredData.getPropertyName() );
- BatchSize batchAnn = property.getAnnotation( BatchSize.class );
- collectionBinder.setBatchSize( batchAnn );
- javax.persistence.OrderBy ejb3OrderByAnn = property.getAnnotation( javax.persistence.OrderBy.class );
- OrderBy orderByAnn = property.getAnnotation( OrderBy.class );
- collectionBinder.setEjb3OrderBy( ejb3OrderByAnn );
- collectionBinder.setSqlOrderBy( orderByAnn );
- Sort sortAnn = property.getAnnotation( Sort.class );
- collectionBinder.setSort( sortAnn );
- Cache cachAnn = property.getAnnotation( Cache.class );
- collectionBinder.setCache( cachAnn );
- collectionBinder.setPropertyHolder( propertyHolder );
- Cascade hibernateCascade = property.getAnnotation( Cascade.class );
- NotFound notFound = property.getAnnotation( NotFound.class );
- boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );
- collectionBinder.setIgnoreNotFound( ignoreNotFound );
- collectionBinder.setCollectionType( inferredData.getProperty().getElementClass() );
- collectionBinder.setMappings( mappings );
- collectionBinder.setAccessType( inferredData.getDefaultAccess() );
- Ejb3Column[] elementColumns;
- //do not use "element" if you are a JPA 2 @ElementCollection only for legacy Hibernate mappings
- boolean isJPA2ForValueMapping = property.isAnnotationPresent( ElementCollection.class );
- PropertyData virtualProperty = isJPA2ForValueMapping ? inferredData : new WrappedInferredData(
- inferredData, "element"
- );
- if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent(
- Formula.class
- ) ) {
- Column ann = property.getAnnotation( Column.class );
- Formula formulaAnn = property.getAnnotation( Formula.class );
- elementColumns = Ejb3Column.buildColumnFromAnnotation(
- new Column[] { ann },
- formulaAnn,
- nullability,
- propertyHolder,
- virtualProperty,
- entityBinder.getSecondaryTables(),
- mappings
- );
- }
- else if ( property.isAnnotationPresent( Columns.class ) ) {
- Columns anns = property.getAnnotation( Columns.class );
- elementColumns = Ejb3Column.buildColumnFromAnnotation(
- anns.columns(), null, nullability, propertyHolder, virtualProperty,
- entityBinder.getSecondaryTables(), mappings
- );
- }
- else {
- elementColumns = Ejb3Column.buildColumnFromAnnotation(
- null,
- null,
- nullability,
- propertyHolder,
- virtualProperty,
- entityBinder.getSecondaryTables(),
- mappings
- );
- }
- {
- Column[] keyColumns = null;
- //JPA 2 has priority and has different default column values, differenciate legacy from JPA 2
- Boolean isJPA2 = null;
- if ( property.isAnnotationPresent( MapKeyColumn.class ) ) {
- isJPA2 = Boolean.TRUE;
- keyColumns = new Column[] { new MapKeyColumnDelegator( property.getAnnotation( MapKeyColumn.class ) ) };
- }
- else if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) ) {
- if ( isJPA2 == null ) {
- isJPA2 = Boolean.FALSE;
- }
- keyColumns = property.getAnnotation( org.hibernate.annotations.MapKey.class ).columns();
- }
- //not explicitly legacy
- if ( isJPA2 == null ) {
- isJPA2 = Boolean.TRUE;
- }
- //nullify empty array
- keyColumns = keyColumns != null && keyColumns.length > 0 ? keyColumns : null;
- //"mapkey" is the legacy column name of the key column pre JPA 2
- PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" );
- Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation(
- keyColumns,
- null,
- Nullability.FORCED_NOT_NULL,
- propertyHolder,
- isJPA2 ? inferredData : mapKeyVirtualProperty,
- isJPA2 ? "_KEY" : null,
- entityBinder.getSecondaryTables(),
- mappings
- );
- collectionBinder.setMapKeyColumns( mapColumns );
- }
- {
- JoinColumn[] joinKeyColumns = null;
- //JPA 2 has priority and has different default column values, differenciate legacy from JPA 2
- Boolean isJPA2 = null;
- if ( property.isAnnotationPresent( MapKeyJoinColumns.class ) ) {
- isJPA2 = Boolean.TRUE;
- final MapKeyJoinColumn[] mapKeyJoinColumns = property.getAnnotation( MapKeyJoinColumns.class )
- .value();
- joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
- int index = 0;
- for ( MapKeyJoinColumn joinColumn : mapKeyJoinColumns ) {
- joinKeyColumns[index] = new MapKeyJoinColumnDelegator( joinColumn );
- index++;
- }
- if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {
- throw new AnnotationException(
- "@MapKeyJoinColumn and @MapKeyJoinColumns used on the same property: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- }
- else if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {
- isJPA2 = Boolean.TRUE;
- joinKeyColumns = new JoinColumn[] {
- new MapKeyJoinColumnDelegator(
- property.getAnnotation(
- MapKeyJoinColumn.class
- )
- )
- };
- }
- else if ( property.isAnnotationPresent( org.hibernate.annotations.MapKeyManyToMany.class ) ) {
- if ( isJPA2 == null ) {
- isJPA2 = Boolean.FALSE;
- }
- joinKeyColumns = property.getAnnotation( org.hibernate.annotations.MapKeyManyToMany.class )
- .joinColumns();
- }
- //not explicitly legacy
- if ( isJPA2 == null ) {
- isJPA2 = Boolean.TRUE;
- }
- PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" );
- Ejb3JoinColumn[] mapJoinColumns = Ejb3JoinColumn.buildJoinColumnsWithDefaultColumnSuffix(
- joinKeyColumns,
- null,
- entityBinder.getSecondaryTables(),
- propertyHolder,
- isJPA2 ? inferredData.getPropertyName() : mapKeyVirtualProperty.getPropertyName(),
- isJPA2 ? "_KEY" : null,
- mappings
- );
- collectionBinder.setMapKeyManyToManyColumns( mapJoinColumns );
- }
- //potential element
- collectionBinder.setEmbedded( property.isAnnotationPresent( Embedded.class ) );
- collectionBinder.setElementColumns( elementColumns );
- collectionBinder.setProperty( property );
- //TODO enhance exception with @ManyToAny and @CollectionOfElements
- if ( oneToManyAnn != null && manyToManyAnn != null ) {
- throw new AnnotationException(
- "@OneToMany and @ManyToMany on the same property is not allowed: "
- + propertyHolder.getEntityName() + "." + inferredData.getPropertyName()
- );
- }
- String mappedBy = null;
- if ( oneToManyAnn != null ) {
- for ( Ejb3JoinColumn column : joinColumns ) {
- if ( column.isSecondary() ) {
- throw new NotYetImplementedException( "Collections having FK in secondary table" );
- }
- }
- collectionBinder.setFkJoinColumns( joinColumns );
- mappedBy = oneToManyAnn.mappedBy();
- collectionBinder.setTargetEntity(
- mappings.getReflectionManager().toXClass( oneToManyAnn.targetEntity() )
- );
- collectionBinder.setCascadeStrategy(
- getCascadeStrategy(
- oneToManyAnn.cascade(), hibernateCascade, oneToManyAnn.orphanRemoval(), false
- )
- );
- collectionBinder.setOneToMany( true );
- }
- else if ( elementCollectionAnn != null
- || collectionOfElementsAnn != null //Hibernate legacy
- ) {
- for ( Ejb3JoinColumn column : joinColumns ) {
- if ( column.isSecondary() ) {
- throw new NotYetImplementedException( "Collections having FK in secondary table" );
- }
- }
- collectionBinder.setFkJoinColumns( joinColumns );
- mappedBy = "";
- final Class<?> targetElement = elementCollectionAnn != null ?
- elementCollectionAnn.targetClass() :
- collectionOfElementsAnn.targetElement();
- collectionBinder.setTargetEntity(
- mappings.getReflectionManager().toXClass( targetElement )
- );
- //collectionBinder.setCascadeStrategy( getCascadeStrategy( embeddedCollectionAnn.cascade(), hibernateCascade ) );
- collectionBinder.setOneToMany( true );
- }
- else if ( manyToManyAnn != null ) {
- mappedBy = manyToManyAnn.mappedBy();
- collectionBinder.setTargetEntity(
- mappings.getReflectionManager().toXClass( manyToManyAnn.targetEntity() )
- );
- collectionBinder.setCascadeStrategy(
- getCascadeStrategy(
- manyToManyAnn.cascade(), hibernateCascade, false, false
- )
- );
- collectionBinder.setOneToMany( false );
- }
- else if ( property.isAnnotationPresent( ManyToAny.class ) ) {
- mappedBy = "";
- collectionBinder.setTargetEntity(
- mappings.getReflectionManager().toXClass( void.class )
- );
- collectionBinder.setCascadeStrategy( getCascadeStrategy( null, hibernateCascade, false, false ) );
- collectionBinder.setOneToMany( false );
- }
- collectionBinder.setMappedBy( mappedBy );
- bindJoinedTableAssociation(
- property, mappings, entityBinder, collectionBinder, propertyHolder, inferredData, mappedBy
- );
- OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
- boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );
- collectionBinder.setCascadeDeleteEnabled( onDeleteCascade );
- if ( isIdentifierMapper ) {
- collectionBinder.setInsertable( false );
- collectionBinder.setUpdatable( false );
- }
- if ( property.isAnnotationPresent( CollectionId.class ) ) { //do not compute the generators unless necessary
- HashMap<String, IdGenerator> localGenerators = ( HashMap<String, IdGenerator> ) classGenerators.clone();
- localGenerators.putAll( buildLocalGenerators( property, mappings ) );
- collectionBinder.setLocalGenerators( localGenerators );
- }
- collectionBinder.setInheritanceStatePerClass( inheritanceStatePerClass );
- collectionBinder.setDeclaringClass( inferredData.getDeclaringClass() );
- collectionBinder.bind();
- }
- //Either a regular property or a basic @Id or @EmbeddedId while not ignoring id annotations
- else if ( !isId || !entityBinder.isIgnoreIdAnnotations() ) {
- //define whether the type is a component or not
- boolean isComponent = false;
- //Overrides from @MapsId if needed
- boolean isOverridden = false;
- if ( isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
- //the associated entity could be using an @IdClass making the overridden property a component
- final PropertyData overridingProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
- isId, propertyHolder, property.getName(), mappings
- );
- if ( overridingProperty != null ) {
- isOverridden = true;
- final InheritanceState state = inheritanceStatePerClass.get( overridingProperty.getClassOrElement() );
- if ( state != null ) {
- isComponent = isComponent || state.hasIdClassOrEmbeddedId();
- }
- //Get the new column
- columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty( isId );
- }
- }
- isComponent = isComponent
- || property.isAnnotationPresent( Embedded.class )
- || property.isAnnotationPresent( EmbeddedId.class )
- || returnedClass.isAnnotationPresent( Embeddable.class );
- if ( isComponent ) {
- String referencedEntityName = null;
- if ( isOverridden ) {
- final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
- isId, propertyHolder, property.getName(), mappings
- );
- referencedEntityName = mapsIdProperty.getClassOrElementName();
- }
- AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );
- propertyBinder = bindComponent(
- inferredData,
- propertyHolder,
- propertyAccessor,
- entityBinder,
- isIdentifierMapper,
- mappings,
- isComponentEmbedded,
- isId,
- inheritanceStatePerClass,
- referencedEntityName,
- isOverridden ? ( Ejb3JoinColumn[] ) columns : null
- );
- }
- else {
- //provide the basic property mapping
- boolean optional = true;
- boolean lazy = false;
- if ( property.isAnnotationPresent( Basic.class ) ) {
- Basic ann = property.getAnnotation( Basic.class );
- optional = ann.optional();
- lazy = ann.fetch() == FetchType.LAZY;
- }
- //implicit type will check basic types and Serializable classes
- if ( isId || ( !optional && nullability != Nullability.FORCED_NULL ) ) {
- //force columns to not null
- for ( Ejb3Column col : columns ) {
- col.forceNotNull();
- }
- }
- propertyBinder.setLazy( lazy );
- propertyBinder.setColumns( columns );
- if ( isOverridden ) {
- final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
- isId, propertyHolder, property.getName(), mappings
- );
- propertyBinder.setReferencedEntityName( mapsIdProperty.getClassOrElementName() );
- }
- propertyBinder.makePropertyValueAndBind();
- }
- if ( isOverridden ) {
- final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
- isId, propertyHolder, property.getName(), mappings
- );
- Map<String, IdGenerator> localGenerators = ( HashMap<String, IdGenerator> ) classGenerators.clone();
- final IdGenerator foreignGenerator = new IdGenerator();
- foreignGenerator.setIdentifierGeneratorStrategy( "assigned" );
- foreignGenerator.setName( "Hibernate-local--foreign generator" );
- foreignGenerator.setIdentifierGeneratorStrategy( "foreign" );
- foreignGenerator.addParam( "property", mapsIdProperty.getPropertyName() );
- localGenerators.put( foreignGenerator.getName(), foreignGenerator );
- BinderHelper.makeIdGenerator(
- ( SimpleValue ) propertyBinder.getValue(),
- foreignGenerator.getIdentifierGeneratorStrategy(),
- foreignGenerator.getName(),
- mappings,
- localGenerators
- );
- }
- if ( isId ) {
- //components and regular basic types create SimpleValue objects
- final SimpleValue value = ( SimpleValue ) propertyBinder.getValue();
- if ( !isOverridden ) {
- processId(
- propertyHolder,
- inferredData,
- value,
- classGenerators,
- isIdentifierMapper,
- mappings
- );
- }
- }
- }
- }
- //init index
- //process indexes after everything: in second pass, many to one has to be done before indexes
- Index index = property.getAnnotation( Index.class );
- if ( index != null ) {
- if ( joinColumns != null ) {
- for ( Ejb3Column column : joinColumns ) {
- column.addIndex( index, inSecondPass );
- }
- }
- else {
- if ( columns != null ) {
- for ( Ejb3Column column : columns ) {
- column.addIndex( index, inSecondPass );
- }
- }
- }
- }
- NaturalId naturalIdAnn = property.getAnnotation( NaturalId.class );
- if ( naturalIdAnn != null ) {
- if ( joinColumns != null ) {
- for ( Ejb3Column column : joinColumns ) {
- column.addUniqueKey( "_UniqueKey", inSecondPass );
- }
- }
- else {
- for ( Ejb3Column column : columns ) {
- column.addUniqueKey( "_UniqueKey", inSecondPass );
- }
- }
- }
- //添加自定义注释的处理
- CommentBinder.bindColumnComment(property, columns);
- //CommentBinder.bindTableComment(clazzToProcess, persistentClass);
- //CommentBinder.bindColumnComment(property, column);
- }
- private static void setVersionInformation(XProperty property, PropertyBinder propertyBinder) {
- propertyBinder.getSimpleValueBinder().setVersion( true );
- if(property.isAnnotationPresent( Source.class )) {
- Source source = property.getAnnotation( Source.class );
- propertyBinder.getSimpleValueBinder().setTimestampVersionType( source.value().typeName() );
- }
- }
- private static void processId(
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- SimpleValue idValue,
- HashMap<String, IdGenerator> classGenerators,
- boolean isIdentifierMapper,
- Mappings mappings) {
- if ( isIdentifierMapper ) {
- throw new AnnotationException(
- "@IdClass class should not have @Id nor @EmbeddedId properties: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- XClass returnedClass = inferredData.getClassOrElement();
- XProperty property = inferredData.getProperty();
- //clone classGenerator and override with local values
- HashMap<String, IdGenerator> localGenerators = ( HashMap<String, IdGenerator> ) classGenerators.clone();
- localGenerators.putAll( buildLocalGenerators( property, mappings ) );
- //manage composite related metadata
- //guess if its a component and find id data access (property, field etc)
- final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class )
- || property.isAnnotationPresent( EmbeddedId.class );
- GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
- String generatorType = generatedValue != null ?
- generatorType( generatedValue.strategy(), mappings ) :
- "assigned";
- String generatorName = generatedValue != null ?
- generatedValue.generator() :
- BinderHelper.ANNOTATION_STRING_DEFAULT;
- if ( isComponent ) {
- generatorType = "assigned";
- } //a component must not have any generator
- BinderHelper.makeIdGenerator( idValue, generatorType, generatorName, mappings, localGenerators );
- log.trace(
- "Bind {} on {}", ( isComponent ? "@EmbeddedId" : "@Id" ), inferredData.getPropertyName()
- );
- }
- //TODO move that to collection binder?
- private static void bindJoinedTableAssociation(
- XProperty property,
- Mappings mappings,
- EntityBinder entityBinder,
- CollectionBinder collectionBinder,
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- String mappedBy) {
- TableBinder associationTableBinder = new TableBinder();
- JoinColumn[] annJoins;
- JoinColumn[] annInverseJoins;
- JoinTable assocTable = propertyHolder.getJoinTable( property );
- CollectionTable collectionTable = property.getAnnotation( CollectionTable.class );
- if ( assocTable != null || collectionTable != null ) {
- final String catalog;
- final String schema;
- final String tableName;
- final UniqueConstraint[] uniqueConstraints;
- final JoinColumn[] joins;
- final JoinColumn[] inverseJoins;
- //JPA 2 has priority
- if ( collectionTable != null ) {
- catalog = collectionTable.catalog();
- schema = collectionTable.schema();
- tableName = collectionTable.name();
- uniqueConstraints = collectionTable.uniqueConstraints();
- joins = collectionTable.joinColumns();
- inverseJoins = null;
- }
- else {
- catalog = assocTable.catalog();
- schema = assocTable.schema();
- tableName = assocTable.name();
- uniqueConstraints = assocTable.uniqueConstraints();
- joins = assocTable.joinColumns();
- inverseJoins = assocTable.inverseJoinColumns();
- }
- collectionBinder.setExplicitAssociationTable( true );
- if ( !BinderHelper.isEmptyAnnotationValue( schema ) ) {
- associationTableBinder.setSchema( schema );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( catalog ) ) {
- associationTableBinder.setCatalog( catalog );
- }
- if ( !BinderHelper.isEmptyAnnotationValue( tableName ) ) {
- associationTableBinder.setName( tableName );
- }
- associationTableBinder.setUniqueConstraints( uniqueConstraints );
- //set check constaint in the second pass
- annJoins = joins.length == 0 ? null : joins;
- annInverseJoins = inverseJoins == null || inverseJoins.length == 0 ? null : inverseJoins;
- }
- else {
- annJoins = null;
- annInverseJoins = null;
- }
- Ejb3JoinColumn[] joinColumns = Ejb3JoinColumn.buildJoinTableJoinColumns(
- annJoins, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappedBy,
- mappings
- );
- Ejb3JoinColumn[] inverseJoinColumns = Ejb3JoinColumn.buildJoinTableJoinColumns(
- annInverseJoins, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(),
- mappedBy, mappings
- );
- associationTableBinder.setMappings( mappings );
- collectionBinder.setTableBinder( associationTableBinder );
- collectionBinder.setJoinColumns( joinColumns );
- collectionBinder.setInverseJoinColumns( inverseJoinColumns );
- }
- private static PropertyBinder bindComponent(
- PropertyData inferredData,
- PropertyHolder propertyHolder,
- AccessType propertyAccessor,
- EntityBinder entityBinder,
- boolean isIdentifierMapper,
- Mappings mappings,
- boolean isComponentEmbedded,
- boolean isId, //is a identifier
- Map<XClass, InheritanceState> inheritanceStatePerClass,
- String referencedEntityName, //is a component who is overridden by a @MapsId
- Ejb3JoinColumn[] columns) {
- Component comp;
- if ( referencedEntityName != null ) {
- comp = createComponent( propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper, mappings );
- SecondPass sp = new CopyIdentifierComponentSecondPass(
- comp,
- referencedEntityName,
- columns,
- mappings
- );
- mappings.addSecondPass( sp );
- }
- else {
- comp = fillComponent(
- propertyHolder, inferredData, propertyAccessor, !isId, entityBinder,
- isComponentEmbedded, isIdentifierMapper,
- false, mappings, inheritanceStatePerClass
- );
- }
- if ( isId ) {
- comp.setKey( true );
- if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {
- throw new AnnotationException(
- comp.getComponentClassName()
- + " must not have @Id properties when used as an @EmbeddedId: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- if ( referencedEntityName == null && comp.getPropertySpan() == 0 ) {
- throw new AnnotationException(
- comp.getComponentClassName()
- + " has no persistent id property: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- }
- XProperty property = inferredData.getProperty();
- setupComponentTuplizer( property, comp );
- PropertyBinder binder = new PropertyBinder();
- binder.setName( inferredData.getPropertyName() );
- binder.setValue( comp );
- binder.setProperty( inferredData.getProperty() );
- binder.setAccessType( inferredData.getDefaultAccess() );
- binder.setEmbedded( isComponentEmbedded );
- binder.setHolder( propertyHolder );
- binder.setId( isId );
- binder.setEntityBinder( entityBinder );
- binder.setInheritanceStatePerClass( inheritanceStatePerClass );
- binder.setMappings( mappings );
- binder.makePropertyAndBind();
- return binder;
- }
- public static Component fillComponent(
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- AccessType propertyAccessor,
- boolean isNullable,
- EntityBinder entityBinder,
- boolean isComponentEmbedded,
- boolean isIdentifierMapper,
- boolean inSecondPass,
- Mappings mappings,
- Map<XClass, InheritanceState> inheritanceStatePerClass) {
- return fillComponent(
- propertyHolder, inferredData, null, propertyAccessor,
- isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings,
- inheritanceStatePerClass
- );
- }
- public static Component fillComponent(
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- PropertyData baseInferredData, //base inferred data correspond to the entity reproducing inferredData's properties (ie IdClass)
- AccessType propertyAccessor,
- boolean isNullable,
- EntityBinder entityBinder,
- boolean isComponentEmbedded,
- boolean isIdentifierMapper,
- boolean inSecondPass,
- Mappings mappings,
- Map<XClass, InheritanceState> inheritanceStatePerClass) {
- /**
- * inSecondPass can only be used to apply right away the second pass of a composite-element
- * Because it's a value type, there is no bidirectional association, hence second pass
- * ordering does not matter
- */
- Component comp = createComponent( propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper, mappings );
- String subpath = BinderHelper.getPath( propertyHolder, inferredData );
- log.trace( "Binding component with path: {}", subpath );
- PropertyHolder subHolder = PropertyHolderBuilder.buildPropertyHolder(
- comp, subpath,
- inferredData, propertyHolder, mappings
- );
- final XClass xClassProcessed = inferredData.getPropertyClass();
- List<PropertyData> classElements = new ArrayList<PropertyData>();
- XClass returnedClassOrElement = inferredData.getClassOrElement();
- List<PropertyData> baseClassElements = null;
- Map<String, PropertyData> orderedBaseClassElements = new HashMap<String, PropertyData>();
- XClass baseReturnedClassOrElement;
- if ( baseInferredData != null ) {
- baseClassElements = new ArrayList<PropertyData>();
- baseReturnedClassOrElement = baseInferredData.getClassOrElement();
- bindTypeDefs( baseReturnedClassOrElement, mappings );
- PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, xClassProcessed );
- addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
- for ( PropertyData element : baseClassElements ) {
- orderedBaseClassElements.put( element.getPropertyName(), element );
- }
- }
- //embeddable elements can have type defs
- bindTypeDefs( returnedClassOrElement, mappings );
- PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement, xClassProcessed );
- addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );
- //add elements of the embeddable superclass
- XClass superClass = xClassProcessed.getSuperclass();
- while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
- //FIXME: proper support of typevariables incl var resolved at upper levels
- propContainer = new PropertyContainer( superClass, xClassProcessed );
- addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );
- superClass = superClass.getSuperclass();
- }
- if ( baseClassElements != null ) {
- //useful to avoid breaking pre JPA 2 mappings
- if ( !hasAnnotationsOnIdClass( xClassProcessed ) ) {
- for ( int i = 0; i < classElements.size(); i++ ) {
- final PropertyData idClassPropertyData = classElements.get( i );
- final PropertyData entityPropertyData = orderedBaseClassElements.get( idClassPropertyData.getPropertyName() );
- if ( propertyHolder.isInIdClass() ) {
- if ( entityPropertyData == null ) {
- throw new AnnotationException(
- "Property of @IdClass not found in entity "
- + baseInferredData.getPropertyClass().getName() + ": "
- + idClassPropertyData.getPropertyName()
- );
- }
- final boolean hasXToOneAnnotation = entityPropertyData.getProperty()
- .isAnnotationPresent( ManyToOne.class )
- || entityPropertyData.getProperty().isAnnotationPresent( OneToOne.class );
- final boolean isOfDifferentType = !entityPropertyData.getClassOrElement()
- .equals( idClassPropertyData.getClassOrElement() );
- if ( hasXToOneAnnotation && isOfDifferentType ) {
- //don't replace here as we need to use the actual original return type
- //the annotation overriding will be dealt with by a mechanism similar to @MapsId
- }
- else {
- classElements.set( i, entityPropertyData ); //this works since they are in the same order
- }
- }
- else {
- classElements.set( i, entityPropertyData ); //this works since they are in the same order
- }
- }
- }
- }
- for ( PropertyData propertyAnnotatedElement : classElements ) {
- processElementAnnotations(
- subHolder, isNullable ?
- Nullability.NO_CONSTRAINT :
- Nullability.FORCED_NOT_NULL,
- propertyAnnotatedElement,
- new HashMap<String, IdGenerator>(), entityBinder, isIdentifierMapper, isComponentEmbedded,
- inSecondPass, mappings, inheritanceStatePerClass
- );
- XProperty property = propertyAnnotatedElement.getProperty();
- if ( property.isAnnotationPresent( GeneratedValue.class ) &&
- property.isAnnotationPresent( Id.class ) ) {
- //clone classGenerator and override with local values
- Map<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
- localGenerators.putAll( buildLocalGenerators( property, mappings ) );
- GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
- String generatorType = generatedValue != null ? generatorType(
- generatedValue.strategy(), mappings
- ) : "assigned";
- String generator = generatedValue != null ? generatedValue.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;
- BinderHelper.makeIdGenerator(
- ( SimpleValue ) comp.getProperty( property.getName() ).getValue(),
- generatorType,
- generator,
- mappings,
- localGenerators
- );
- }
- }
- return comp;
- }
- public static Component createComponent(
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- boolean isComponentEmbedded,
- boolean isIdentifierMapper,
- Mappings mappings) {
- Component comp = new Component( mappings, propertyHolder.getPersistentClass() );
- comp.setEmbedded( isComponentEmbedded );
- //yuk
- comp.setTable( propertyHolder.getTable() );
- //FIXME shouldn't identifier mapper use getClassOrElementName? Need to be checked.
- if ( isIdentifierMapper || ( isComponentEmbedded && inferredData.getPropertyName() == null ) ) {
- comp.setComponentClassName( comp.getOwner().getClassName() );
- }
- else {
- comp.setComponentClassName( inferredData.getClassOrElementName() );
- }
- comp.setNodeName( inferredData.getPropertyName() );
- return comp;
- }
- private static void bindIdClass(
- String generatorType,
- String generatorName,
- PropertyData inferredData,
- PropertyData baseInferredData,
- Ejb3Column[] columns,
- PropertyHolder propertyHolder,
- boolean isComposite,
- AccessType propertyAccessor,
- EntityBinder entityBinder,
- boolean isEmbedded,
- boolean isIdentifierMapper,
- Mappings mappings,
- Map<XClass, InheritanceState> inheritanceStatePerClass) {
- /*
- * Fill simple value and property since and Id is a property
- */
- PersistentClass persistentClass = propertyHolder.getPersistentClass();
- if ( !( persistentClass instanceof RootClass ) ) {
- throw new AnnotationException(
- "Unable to define/override @Id(s) on a subclass: "
- + propertyHolder.getEntityName()
- );
- }
- RootClass rootClass = ( RootClass ) persistentClass;
- String persistentClassName = rootClass.getClassName();
- SimpleValue id;
- final String propertyName = inferredData.getPropertyName();
- HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
- if ( isComposite ) {
- id = fillComponent(
- propertyHolder, inferredData, baseInferredData, propertyAccessor,
- false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass
- );
- Component componentId = ( Component ) id;
- componentId.setKey( true );
- if ( rootClass.getIdentifier() != null ) {
- throw new AnnotationException( componentId.getComponentClassName() + " must not have @Id properties when used as an @EmbeddedId" );
- }
- if ( componentId.getPropertySpan() == 0 ) {
- throw new AnnotationException( componentId.getComponentClassName() + " has no persistent id property" );
- }
- //tuplizers
- XProperty property = inferredData.getProperty();
- setupComponentTuplizer( property, componentId );
- }
- else {
- //TODO I think this branch is never used. Remove.
- for ( Ejb3Column column : columns ) {
- column.forceNotNull(); //this is an id
- }
- SimpleValueBinder value = new SimpleValueBinder();
- value.setPropertyName( propertyName );
- value.setReturnedClassName( inferredData.getTypeName() );
- value.setColumns( columns );
- value.setPersistentClassName( persistentClassName );
- value.setMappings( mappings );
- value.setType( inferredData.getProperty(), inferredData.getClassOrElement() );
- id = value.make();
- }
- rootClass.setIdentifier( id );
- BinderHelper.makeIdGenerator( id, generatorType, generatorName, mappings, localGenerators );
- if ( isEmbedded ) {
- rootClass.setEmbeddedIdentifier( inferredData.getPropertyClass() == null );
- }
- else {
- PropertyBinder binder = new PropertyBinder();
- binder.setName( propertyName );
- binder.setValue( id );
- binder.setAccessType( inferredData.getDefaultAccess() );
- binder.setProperty( inferredData.getProperty() );
- Property prop = binder.makeProperty();
- rootClass.setIdentifierProperty( prop );
- //if the id property is on a superclass, update the metamodel
- final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
- inferredData.getDeclaringClass(),
- inheritanceStatePerClass,
- mappings
- );
- if ( superclass != null ) {
- superclass.setDeclaredIdentifierProperty( prop );
- }
- else {
- //we know the property is on the actual entity
- rootClass.setDeclaredIdentifierProperty( prop );
- }
- }
- }
- private static PropertyData getUniqueIdPropertyFromBaseClass(
- PropertyData inferredData,
- PropertyData baseInferredData,
- AccessType propertyAccessor,
- Mappings mappings) {
- List<PropertyData> baseClassElements = new ArrayList<PropertyData>();
- XClass baseReturnedClassOrElement = baseInferredData.getClassOrElement();
- PropertyContainer propContainer = new PropertyContainer(
- baseReturnedClassOrElement, inferredData.getPropertyClass()
- );
- addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
- //Id properties are on top and there is only one
- return baseClassElements.get( 0 );
- }
- private static void setupComponentTuplizer(XProperty property, Component component) {
- if ( property == null ) {
- return;
- }
- if ( property.isAnnotationPresent( Tuplizers.class ) ) {
- for ( Tuplizer tuplizer : property.getAnnotation( Tuplizers.class ).value() ) {
- EntityMode mode = EntityMode.parse( tuplizer.entityMode() );
- component.addTuplizer( mode, tuplizer.impl().getName() );
- }
- }
- if ( property.isAnnotationPresent( Tuplizer.class ) ) {
- Tuplizer tuplizer = property.getAnnotation( Tuplizer.class );
- EntityMode mode = EntityMode.parse( tuplizer.entityMode() );
- component.addTuplizer( mode, tuplizer.impl().getName() );
- }
- }
- private static void bindManyToOne(
- String cascadeStrategy,
- Ejb3JoinColumn[] columns,
- boolean optional,
- boolean ignoreNotFound,
- boolean cascadeOnDelete,
- XClass targetEntity,
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- boolean unique,
- boolean isIdentifierMapper,
- boolean inSecondPass,
- PropertyBinder propertyBinder,
- Mappings mappings) {
- //All FK columns should be in the same table
- org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne( mappings, columns[0].getTable() );
- // This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne
- if ( unique ) {
- value.markAsLogicalOneToOne();
- }
- value.setReferencedEntityName( ToOneBinder.getReferenceEntityName( inferredData, targetEntity, mappings ) );
- final XProperty property = inferredData.getProperty();
- defineFetchingStrategy( value, property );
- //value.setFetchMode( fetchMode );
- value.setIgnoreNotFound( ignoreNotFound );
- value.setCascadeDeleteEnabled( cascadeOnDelete );
- //value.setLazy( fetchMode != FetchMode.JOIN );
- if ( !optional ) {
- for ( Ejb3JoinColumn column : columns ) {
- column.setNullable( false );
- }
- }
- if ( property.isAnnotationPresent( MapsId.class ) ) {
- //read only
- for ( Ejb3JoinColumn column : columns ) {
- column.setInsertable( false );
- column.setUpdatable( false );
- }
- }
- //Make sure that JPA1 key-many-to-one columns are read only tooj
- boolean hasSpecjManyToOne=false;
- if ( mappings.isSpecjProprietarySyntaxEnabled() ) {
- String columnName = "";
- for ( XProperty prop : inferredData.getDeclaringClass()
- .getDeclaredProperties( AccessType.FIELD.getType() ) ) {
- if ( prop.isAnnotationPresent( Id.class ) && prop.isAnnotationPresent( Column.class ) ) {
- columnName = prop.getAnnotation( Column.class ).name();
- }
- final JoinColumn joinColumn = property.getAnnotation( JoinColumn.class );
- if ( property.isAnnotationPresent( ManyToOne.class ) && joinColumn != null
- && ! BinderHelper.isEmptyAnnotationValue( joinColumn.name() )
- && joinColumn.name().equals( columnName )
- && !property.isAnnotationPresent( MapsId.class ) ) {
- hasSpecjManyToOne = true;
- for ( Ejb3JoinColumn column : columns ) {
- column.setInsertable( false );
- column.setUpdatable( false );
- }
- }
- }
- }
- value.setTypeName( inferredData.getClassOrElementName() );
- final String propertyName = inferredData.getPropertyName();
- value.setTypeUsingReflection( propertyHolder.getClassName(), propertyName );
- ForeignKey fk = property.getAnnotation( ForeignKey.class );
- String fkName = fk != null ?
- fk.name() :
- "";
- if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) {
- value.setForeignKeyName( fkName );
- }
- String path = propertyHolder.getPath() + "." + propertyName;
- FkSecondPass secondPass = new ToOneFkSecondPass(
- value, columns,
- !optional && unique, //cannot have nullable and unique on certain DBs like Derby
- propertyHolder.getEntityOwnerClassName(),
- path, mappings
- );
- if ( inSecondPass ) {
- secondPass.doSecondPass( mappings.getClasses() );
- }
- else {
- mappings.addSecondPass(
- secondPass
- );
- }
- Ejb3Column.checkPropertyConsistency( columns, propertyHolder.getEntityName() + propertyName );
- //PropertyBinder binder = new PropertyBinder();
- propertyBinder.setName( propertyName );
- propertyBinder.setValue( value );
- //binder.setCascade(cascadeStrategy);
- if ( isIdentifierMapper ) {
- propertyBinder.setInsertable( false );
- propertyBinder.setUpdatable( false );
- }
- else if (hasSpecjManyToOne) {
- propertyBinder.setInsertable( false );
- propertyBinder.setUpdatable( false );
- }
- else {
- propertyBinder.setInsertable( columns[0].isInsertable() );
- propertyBinder.setUpdatable( columns[0].isUpdatable() );
- }
- propertyBinder.setColumns( columns );
- propertyBinder.setAccessType( inferredData.getDefaultAccess() );
- propertyBinder.setCascade( cascadeStrategy );
- propertyBinder.setProperty( property );
- propertyBinder.setXToMany( true );
- propertyBinder.makePropertyAndBind();
- }
- protected static void defineFetchingStrategy(ToOne toOne, XProperty property) {
- LazyToOne lazy = property.getAnnotation( LazyToOne.class );
- Fetch fetch = property.getAnnotation( Fetch.class );
- ManyToOne manyToOne = property.getAnnotation( ManyToOne.class );
- OneToOne oneToOne = property.getAnnotation( OneToOne.class );
- FetchType fetchType;
- if ( manyToOne != null ) {
- fetchType = manyToOne.fetch();
- }
- else if ( oneToOne != null ) {
- fetchType = oneToOne.fetch();
- }
- else {
- throw new AssertionFailure(
- "Define fetch strategy on a property not annotated with @OneToMany nor @OneToOne"
- );
- }
- if ( lazy != null ) {
- toOne.setLazy( !( lazy.value() == LazyToOneOption.FALSE ) );
- toOne.setUnwrapProxy( ( lazy.value() == LazyToOneOption.NO_PROXY ) );
- }
- else {
- toOne.setLazy( fetchType == FetchType.LAZY );
- toOne.setUnwrapProxy( false );
- }
- if ( fetch != null ) {
- if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) {
- toOne.setFetchMode( FetchMode.JOIN );
- toOne.setLazy( false );
- toOne.setUnwrapProxy( false );
- }
- else if ( fetch.value() == org.hibernate.annotations.FetchMode.SELECT ) {
- toOne.setFetchMode( FetchMode.SELECT );
- }
- else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) {
- throw new AnnotationException( "Use of FetchMode.SUBSELECT not allowed on ToOne associations" );
- }
- else {
- throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() );
- }
- }
- else {
- toOne.setFetchMode( getFetchMode( fetchType ) );
- }
- }
- private static void bindOneToOne(
- String cascadeStrategy,
- Ejb3JoinColumn[] joinColumns,
- boolean optional,
- FetchMode fetchMode,
- boolean ignoreNotFound,
- boolean cascadeOnDelete,
- XClass targetEntity,
- PropertyHolder propertyHolder,
- PropertyData inferredData, String mappedBy,
- boolean trueOneToOne,
- boolean isIdentifierMapper,
- boolean inSecondPass,
- PropertyBinder propertyBinder,
- Mappings mappings) {
- //column.getTable() => persistentClass.getTable()
- final String propertyName = inferredData.getPropertyName();
- log.trace( "Fetching {} with {}", propertyName, fetchMode );
- boolean mapToPK = true;
- if ( !trueOneToOne ) {
- //try to find a hidden true one to one (FK == PK columns)
- KeyValue identifier = propertyHolder.getIdentifier();
- if ( identifier == null ) {
- //this is a @OneToOne in a @EmbeddedId (the persistentClass.identifier is not set yet, it's being built)
- //by definition the PK cannot refers to itself so it cannot map to itself
- mapToPK = false;
- }
- else {
- Iterator idColumns = identifier.getColumnIterator();
- List<String> idColumnNames = new ArrayList<String>();
- org.hibernate.mapping.Column currentColumn;
- if ( identifier.getColumnSpan() != joinColumns.length ) {
- mapToPK = false;
- }
- else {
- while ( idColumns.hasNext() ) {
- currentColumn = ( org.hibernate.mapping.Column ) idColumns.next();
- idColumnNames.add( currentColumn.getName() );
- }
- for ( Ejb3JoinColumn col : joinColumns ) {
- if ( !idColumnNames.contains( col.getMappingColumn().getName() ) ) {
- mapToPK = false;
- break;
- }
- }
- }
- }
- }
- if ( trueOneToOne || mapToPK || !BinderHelper.isEmptyAnnotationValue( mappedBy ) ) {
- //is a true one-to-one
- //FIXME referencedColumnName ignored => ordering may fail.
- OneToOneSecondPass secondPass = new OneToOneSecondPass(
- mappedBy,
- propertyHolder.getEntityName(),
- propertyName,
- propertyHolder, inferredData, targetEntity, ignoreNotFound, cascadeOnDelete,
- optional, cascadeStrategy, joinColumns, mappings
- );
- if ( inSecondPass ) {
- secondPass.doSecondPass( mappings.getClasses() );
- }
- else {
- mappings.addSecondPass(
- secondPass, BinderHelper.isEmptyAnnotationValue( mappedBy )
- );
- }
- }
- else {
- //has a FK on the table
- bindManyToOne(
- cascadeStrategy, joinColumns, optional, ignoreNotFound, cascadeOnDelete,
- targetEntity,
- propertyHolder, inferredData, true, isIdentifierMapper, inSecondPass,
- propertyBinder, mappings
- );
- }
- }
- private static void bindAny(
- String cascadeStrategy,
- Ejb3JoinColumn[] columns,
- boolean cascadeOnDelete,
- Nullability nullability,
- PropertyHolder propertyHolder,
- PropertyData inferredData,
- EntityBinder entityBinder,
- boolean isIdentifierMapper,
- Mappings mappings) {
- org.hibernate.annotations.Any anyAnn = inferredData.getProperty()
- .getAnnotation( org.hibernate.annotations.Any.class );
- if ( anyAnn == null ) {
- throw new AssertionFailure(
- "Missing @Any annotation: "
- + BinderHelper.getPath( propertyHolder, inferredData )
- );
- }
- Any value = BinderHelper.buildAnyValue(
- anyAnn.metaDef(), columns, anyAnn.metaColumn(), inferredData,
- cascadeOnDelete, nullability, propertyHolder, entityBinder, anyAnn.optional(), mappings
- );
- PropertyBinder binder = new PropertyBinder();
- binder.setName( inferredData.getPropertyName() );
- binder.setValue( value );
- binder.setLazy( anyAnn.fetch() == FetchType.LAZY );
- //binder.setCascade(cascadeStrategy);
- if ( isIdentifierMapper ) {
- binder.setInsertable( false );
- binder.setUpdatable( false );
- }
- else {
- binder.setInsertable( columns[0].isInsertable() );
- binder.setUpdatable( columns[0].isUpdatable() );
- }
- binder.setAccessType( inferredData.getDefaultAccess() );
- binder.setCascade( cascadeStrategy );
- Property prop = binder.makeProperty();
- //composite FK columns are in the same table so its OK
- propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
- }
- private static String generatorType(GenerationType generatorEnum, Mappings mappings) {
- boolean useNewGeneratorMappings = mappings.useNewGeneratorMappings();
- switch ( generatorEnum ) {
- case IDENTITY:
- return "identity";
- case AUTO:
- return useNewGeneratorMappings
- ? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
- : "native";
- case TABLE:
- return useNewGeneratorMappings
- ? org.hibernate.id.enhanced.TableGenerator.class.getName()
- : MultipleHiLoPerTableGenerator.class.getName();
- case SEQUENCE:
- return useNewGeneratorMappings
- ? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
- : "seqhilo";
- }
- throw new AssertionFailure( "Unknown GeneratorType: " + generatorEnum );
- }
- private static EnumSet<CascadeType> convertToHibernateCascadeType(javax.persistence.CascadeType[] ejbCascades) {
- EnumSet<CascadeType> hibernateCascadeSet = EnumSet.noneOf( CascadeType.class );
- if ( ejbCascades != null && ejbCascades.length > 0 ) {
- for ( javax.persistence.CascadeType cascade : ejbCascades ) {
- switch ( cascade ) {
- case ALL:
- hibernateCascadeSet.add( CascadeType.ALL );
- break;
- case PERSIST:
- hibernateCascadeSet.add( CascadeType.PERSIST );
- break;
- case MERGE:
- hibernateCascadeSet.add( CascadeType.MERGE );
- break;
- case REMOVE:
- hibernateCascadeSet.add( CascadeType.REMOVE );
- break;
- case REFRESH:
- hibernateCascadeSet.add( CascadeType.REFRESH );
- break;
- case DETACH:
- hibernateCascadeSet.add( CascadeType.DETACH );
- break;
- }
- }
- }
- return hibernateCascadeSet;
- }
- private static String getCascadeStrategy(
- javax.persistence.CascadeType[] ejbCascades,
- Cascade hibernateCascadeAnnotation,
- boolean orphanRemoval,
- boolean forcePersist) {
- EnumSet<CascadeType> hibernateCascadeSet = convertToHibernateCascadeType( ejbCascades );
- CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null ?
- null :
- hibernateCascadeAnnotation.value();
- if ( hibernateCascades != null && hibernateCascades.length > 0 ) {
- hibernateCascadeSet.addAll( Arrays.asList( hibernateCascades ) );
- }
- if ( orphanRemoval ) {
- hibernateCascadeSet.add( CascadeType.DELETE_ORPHAN );
- hibernateCascadeSet.add( CascadeType.REMOVE );
- }
- if ( forcePersist ) {
- hibernateCascadeSet.add( CascadeType.PERSIST );
- }
- StringBuilder cascade = new StringBuilder();
- for ( CascadeType aHibernateCascadeSet : hibernateCascadeSet ) {
- switch ( aHibernateCascadeSet ) {
- case ALL:
- cascade.append( "," ).append( "all" );
- break;
- case SAVE_UPDATE:
- cascade.append( "," ).append( "save-update" );
- break;
- case PERSIST:
- cascade.append( "," ).append( "persist" );
- break;
- case MERGE:
- cascade.append( "," ).append( "merge" );
- break;
- case LOCK:
- cascade.append( "," ).append( "lock" );
- break;
- case REFRESH:
- cascade.append( "," ).append( "refresh" );
- break;
- case REPLICATE:
- cascade.append( "," ).append( "replicate" );
- break;
- case EVICT:
- case DETACH:
- cascade.append( "," ).append( "evict" );
- break;
- case DELETE:
- cascade.append( "," ).append( "delete" );
- break;
- case DELETE_ORPHAN:
- cascade.append( "," ).append( "delete-orphan" );
- break;
- case REMOVE:
- cascade.append( "," ).append( "delete" );
- break;
- }
- }
- return cascade.length() > 0 ?
- cascade.substring( 1 ) :
- "none";
- }
- public static FetchMode getFetchMode(FetchType fetch) {
- if ( fetch == FetchType.EAGER ) {
- return FetchMode.JOIN;
- }
- else {
- return FetchMode.SELECT;
- }
- }
- private static HashMap<String, IdGenerator> buildLocalGenerators(XAnnotatedElement annElt, Mappings mappings) {
- HashMap<String, IdGenerator> generators = new HashMap<String, IdGenerator>();
- TableGenerator tabGen = annElt.getAnnotation( TableGenerator.class );
- SequenceGenerator seqGen = annElt.getAnnotation( SequenceGenerator.class );
- GenericGenerator genGen = annElt.getAnnotation( GenericGenerator.class );
- if ( tabGen != null ) {
- IdGenerator idGen = buildIdGenerator( tabGen, mappings );
- generators.put( idGen.getName(), idGen );
- }
- if ( seqGen != null ) {
- IdGenerator idGen = buildIdGenerator( seqGen, mappings );
- generators.put( idGen.getName(), idGen );
- }
- if ( genGen != null ) {
- IdGenerator idGen = buildIdGenerator( genGen, mappings );
- generators.put( idGen.getName(), idGen );
- }
- return generators;
- }
- public static boolean isDefault(XClass clazz, Mappings mappings) {
- return mappings.getReflectionManager().equals( clazz, void.class );
- }
- /**
- * For the mapped entities build some temporary data-structure containing information about the
- * inheritance status of a class.
- *
- * @param orderedClasses Order list of all annotated entities and their mapped superclasses
- *
- * @return A map of {@code InheritanceState}s keyed against their {@code XClass}.
- */
- public static Map<XClass, InheritanceState> buildInheritanceStates(
- List<XClass> orderedClasses,
- Mappings mappings) {
- ReflectionManager reflectionManager = mappings.getReflectionManager();
- Map<XClass, InheritanceState> inheritanceStatePerClass = new HashMap<XClass, InheritanceState>(
- orderedClasses.size()
- );
- for ( XClass clazz : orderedClasses ) {
- InheritanceState superclassState = InheritanceState.getSuperclassInheritanceState(
- clazz, inheritanceStatePerClass
- );
- InheritanceState state = new InheritanceState( clazz, inheritanceStatePerClass, mappings );
- if ( superclassState != null ) {
- //the classes are ordered thus preventing an NPE
- //FIXME if an entity has subclasses annotated @MappedSperclass wo sub @Entity this is wrong
- superclassState.setHasSiblings( true );
- InheritanceState superEntityState = InheritanceState.getInheritanceStateOfSuperEntity(
- clazz, inheritanceStatePerClass
- );
- state.setHasParents( superEntityState != null );
- final boolean nonDefault = state.getType() != null && !InheritanceType.SINGLE_TABLE
- .equals( state.getType() );
- if ( superclassState.getType() != null ) {
- final boolean mixingStrategy = state.getType() != null && !state.getType()
- .equals( superclassState.getType() );
- if ( nonDefault && mixingStrategy ) {
- log.warn(
- "Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: {}",
- clazz.getName()
- );
- }
- state.setType( superclassState.getType() );
- }
- }
- inheritanceStatePerClass.put( clazz, state );
- }
- return inheritanceStatePerClass;
- }
- private static boolean hasAnnotationsOnIdClass(XClass idClass) {
- // if(idClass.getAnnotation(Embeddable.class) != null)
- // return true;
- List<XProperty> properties = idClass.getDeclaredProperties( XClass.ACCESS_FIELD );
- for ( XProperty property : properties ) {
- if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( OneToMany.class ) ||
- property.isAnnotationPresent( ManyToOne.class ) || property.isAnnotationPresent( Id.class ) ||
- property.isAnnotationPresent( GeneratedValue.class ) || property.isAnnotationPresent( OneToOne.class ) ||
- property.isAnnotationPresent( ManyToMany.class )
- ) {
- return true;
- }
- }
- List<XMethod> methods = idClass.getDeclaredMethods();
- for ( XMethod method : methods ) {
- if ( method.isAnnotationPresent( Column.class ) || method.isAnnotationPresent( OneToMany.class ) ||
- method.isAnnotationPresent( ManyToOne.class ) || method.isAnnotationPresent( Id.class ) ||
- method.isAnnotationPresent( GeneratedValue.class ) || method.isAnnotationPresent( OneToOne.class ) ||
- method.isAnnotationPresent( ManyToMany.class )
- ) {
- return true;
- }
- }
- return false;
- }
- }