📄 annotationbinder.java
字号:
rootClass.setPolymorphic( true ); log.debug( "Setting discriminator for entity " + rootClass.getEntityName() ); } } /** * Add elements of a class */ private static boolean addElementsOfAClass( List<PropertyData> elements, PropertyHolder propertyHolder, boolean isPropertyAnnotated, String propertyAccessor, final XClass annotatedClass, ExtendedMappings mappings ) { boolean hasIdentifier = false; AccessType access = annotatedClass.getAnnotation( AccessType.class ); String localPropertyAccessor = access != null ? access.value() : null; String accessType = null; if ( "property".equals( localPropertyAccessor ) || "field".equals( localPropertyAccessor ) ) { accessType = localPropertyAccessor; } else { if ( localPropertyAccessor == null ) { localPropertyAccessor = propertyAccessor; } if ( isPropertyAnnotated ) { accessType = "property"; } else { accessType = "field"; } } log.debug( "Processing " + propertyHolder.getEntityName() + " " + accessType + " annotation" ); List<XProperty> properties = annotatedClass.getDeclaredProperties( accessType ); //order so that property are used in the same order when binding native query Collections.sort( properties, new Comparator<XProperty>() { public int compare(XProperty property1, XProperty property2) { return property1.getName().compareTo( property2.getName() ); } } ); for (XProperty p : properties) { if ( !p.isTypeResolved() && !discoverTypeWithoutReflection( p ) && !mustBeSkipped( p, mappings ) ) { throw new AnnotationException( "Property " + StringHelper.qualify( propertyHolder.getEntityName(), p.getName() ) + " has an unbound type and no explicit target entity. Resolve this Generic usage issue" + " or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type" ); } final boolean currentHasIdentifier = addProperty( p, elements, localPropertyAccessor, mappings ); hasIdentifier = hasIdentifier || currentHasIdentifier; } return hasIdentifier; } private static boolean discoverTypeWithoutReflection(XProperty p) { if ( p.isAnnotationPresent( OneToOne.class ) && !p.getAnnotation( OneToOne.class ) .targetEntity() .equals( void.class ) ) { return true; } else if ( p.isAnnotationPresent( OneToMany.class ) && !p.getAnnotation( OneToMany.class ) .targetEntity() .equals( void.class ) ) { return true; } else if ( p.isAnnotationPresent( ManyToOne.class ) && !p.getAnnotation( ManyToOne.class ) .targetEntity() .equals( void.class ) ) { return true; } else if ( p.isAnnotationPresent( ManyToMany.class ) && !p.getAnnotation( ManyToMany.class ) .targetEntity() .equals( void.class ) ) { return true; } else if ( p.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) { return true; } else if ( p.isAnnotationPresent( ManyToAny.class ) ) { if ( !p.isCollection() && !p.isArray() ) { throw new AnnotationException( "@ManyToAny used on a non collection non array property: " + p.getName() ); } return true; } else if ( p.isAnnotationPresent( Type.class ) ) { return true; } else if ( p.isAnnotationPresent( Target.class ) ) { return true; } return false; } private static boolean addProperty( XProperty property, List<PropertyData> annElts, String propertyAccessor, ExtendedMappings mappings ) { boolean hasIdentifier = false; PropertyData propertyAnnotatedElement = new PropertyInferredData( property, propertyAccessor, mappings.getReflectionManager() ); if ( !mustBeSkipped( propertyAnnotatedElement.getProperty(), mappings ) ) { /* * put element annotated by @Id in front * since it has to be parsed before any assoctation by Hibernate */ final XAnnotatedElement element = propertyAnnotatedElement.getProperty(); if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) { annElts.add( 0, propertyAnnotatedElement ); hasIdentifier = true; } else { annElts.add( propertyAnnotatedElement ); hasIdentifier = false; } } return hasIdentifier; } private static boolean mustBeSkipped(XProperty property, ExtendedMappings mappings) { //TODO make those hardcoded tests more portable (through the bytecode provider?) return property.isAnnotationPresent( Transient.class ) || "net.sf.cglib.transform.impl.InterceptFieldCallback".equals( property.getType().getName() ) || "org.hibernate.bytecode.javassist.FieldHandler".equals( property.getType().getName() ); } /** * Process annotation of a particular property */ private static void processElementAnnotations( PropertyHolder propertyHolder, Nullability nullability, XProperty property, PropertyData inferredData, HashMap<String, IdGenerator> classGenerators, EntityBinder entityBinder, boolean isIdentifierMapper, boolean isComponentEmbedded, boolean inSecondPass, ExtendedMappings mappings ) 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 */ Ejb3Column[] columns = null; Ejb3JoinColumn[] joinColumns = null; if ( log.isDebugEnabled() ) { log.debug( "Processing annotations of " + propertyHolder.getEntityName() + "." + inferredData.getPropertyName() ); } if ( property.isAnnotationPresent( Parent.class ) ) { if ( propertyHolder.isComponent() ) { propertyHolder.setParentProperty( property.getName() ); } else { throw new AnnotationException( "@Parent cannot be applied outside an embeddable object: " + StringHelper.qualify( propertyHolder.getPath(), property.getName() ) ); } return; } //process @JoinColumn(s) before @Column(s) to handle collection of elements properly { JoinColumn[] anns = null; if ( property.isAnnotationPresent( JoinColumn.class ) ) { anns = new JoinColumn[] { property.getAnnotation( JoinColumn.class ) }; } else if ( property.isAnnotationPresent( JoinColumns.class ) ) { JoinColumns ann = property.getAnnotation( JoinColumns.class ); anns = ann.value(); int length = anns.length; if ( length == 0 ) { throw new AnnotationException( "Cannot bind an empty @JoinColumns" ); } } if ( anns != null ) { joinColumns = Ejb3JoinColumn.buildJoinColumns( anns, null, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappings ); } } if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( Formula.class ) ) { Column ann = property.getAnnotation( Column.class ); Formula formulaAnn = property.getAnnotation( Formula.class ); columns = Ejb3Column.buildColumnFromAnnotation( new Column[] { ann }, formulaAnn, nullability, propertyHolder, inferredData, entityBinder.getSecondaryTables(), mappings ); } else if ( property.isAnnotationPresent( Columns.class ) ) { Columns anns = property.getAnnotation( Columns.class ); columns = Ejb3Column.buildColumnFromAnnotation( anns.columns(), null, nullability, propertyHolder, inferredData, entityBinder.getSecondaryTables(), mappings ); } //set default values if needed if ( joinColumns == null && ( property.isAnnotationPresent( ManyToOne.class ) || property.isAnnotationPresent( OneToOne.class ) ) ) { if ( property.isAnnotationPresent( JoinTable.class ) ) { JoinTable joinTableAnn = property.getAnnotation( JoinTable.class ); joinColumns = Ejb3JoinColumn.buildJoinColumns( joinTableAnn.inverseJoinColumns(), null, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappings ); if ( StringHelper.isEmpty( joinTableAnn.name() ) ) { throw new AnnotationException( "JoinTable.name() on a @ToOne association has to be explicit: " + StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() ) ); } } else { OneToOne oneToOneAnn = property.getAnnotation( OneToOne.class ); String mappedBy = oneToOneAnn != null ? oneToOneAnn.mappedBy() : null; joinColumns = Ejb3JoinColumn.buildJoinColumns( (JoinColumn[]) null, mappedBy, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappings ); } } else if ( joinColumns == null && ( property.isAnnotationPresent( OneToMany.class ) || property.isAnnotationPresent( CollectionOfElements.class ) ) ) { OneToMany oneToMany = property.getAnnotation( OneToMany.class ); String mappedBy = oneToMany != null ? oneToMany.mappedBy() : ""; joinColumns = Ejb3JoinColumn.buildJoinColumns( (JoinColumn[]) null, mappedBy, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), mappings ); } else if ( joinColumns == null && property.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) { throw new AnnotationException( "@Any requires an explicit @JoinColumn(s): " + StringHelper.qualify( propertyHolder.getPath(), property.getName() ) ); } if ( columns == null && !property.isAnnotationPresent( ManyToMany.class ) ) { //useful for collection of embedded elements columns = Ejb3Column.buildColumnFromAnnotation( null, null, nullability, propertyHolder, inferredData, entityBinder.getSecondaryTables(), mappings ); } if ( nullability == Nullability.FORCED_NOT_NULL ) { //force columns to not null for (Ejb3Column col : columns) { col.forceNotNull(); } } final XClass returnedClass = inferredData.getClassOrElement(); if ( !entityBinder.isIgnoreIdAnnotations() && ( property.isAnnotationPresent( Id.class ) || property.isAnnotationPresent( EmbeddedId.class ) ) ) { if ( isIdentifierMapper ) { throw new AnnotationException( "@IdClass class should not have @Id nor @EmbeddedId properties" ); } log.debug( inferredData.getPropertyName() + " is an id" ); //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 ); boolean propertyAnnotated = entityBinder.isPropertyAnnotated( returnedClass ); String propertyAccessor = entityBinder.getPropertyAccessor( returnedClass ); //if ( isComponent && embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD ) propertyAccess = false; GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class ); String generatorType = generatedValue != null ? generatorType( generatedValue.strategy() ) : "assigned"; String generator = generatedValue != null ? generatedValue.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT; if ( isComponent ) generatorType = "assigned"; //a component must not have any generator Type typeAnn = property.getAnnotation( Type.class ); bindId( generatorType, generator, inferredData, columns, propertyHolder, localGenerators, isComponent, propertyAnnotated, propertyAccessor, entityBinder, typeAnn, false, isIdentifierMapper, mappings ); if ( log.isDebugEnabled() ) { log.debug( "Bind " + ( isComponent ? "@EmbeddedId" : "@Id" ) + " on " + inferredData.getPropertyName() ); } } else 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(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -