📄 collectionbinder.java
字号:
else if ( anyAnn != null ) { if ( !property.isAnnotationPresent( JoinTable.class ) ) { String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName(); throw new AnnotationException( "@JoinTable is mandatory when @ManyToAny is used: " + path ); } } else { JoinTable joinTableAnn = property.getAnnotation( JoinTable.class ); if ( joinTableAnn != null && joinTableAnn.inverseJoinColumns().length > 0 ) { String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName(); throw new AnnotationException( "Use of @JoinTable.inverseJoinColumns targeting an unmapped class: " + path + "[" + collType + "]" ); } } } boolean mappedBy = !BinderHelper.isDefault( joinColumns[0].getMappedBy() ); if ( mappedBy ) { if ( !isCollectionOfEntities ) { StringBuilder error = new StringBuilder( 80 ) .append( "Collection of elements must not have mappedBy or association reference an unmapped entity: " ) .append( collValue.getOwnerEntityName() ) .append( "." ) .append( joinColumns[0].getPropertyName() ); throw new AnnotationException( error.toString() ); } Property otherSideProperty; try { otherSideProperty = collectionEntity.getRecursiveProperty( joinColumns[0].getMappedBy() ); } catch (MappingException e) { StringBuilder error = new StringBuilder( 80 ); error.append( "mappedBy reference an unknown target entity property: " ) .append( collType ).append( "." ).append( joinColumns[0].getMappedBy() ) .append( " in " ) .append( collValue.getOwnerEntityName() ) .append( "." ) .append( joinColumns[0].getPropertyName() ); throw new AnnotationException( error.toString() ); } Table table; if ( otherSideProperty.getValue() instanceof Collection ) { //this is a collection on the other side table = ( (Collection) otherSideProperty.getValue() ).getCollectionTable(); } else { //This is a ToOne with a @JoinTable or a regular property table = otherSideProperty.getValue().getTable(); } collValue.setCollectionTable( table ); String entityName = collectionEntity.getEntityName(); for (Ejb3JoinColumn column : joinColumns) { //column.setDefaultColumnHeader( joinColumns[0].getMappedBy() ); //seems not to be used, make sense column.setManyToManyOwnerSideEntityName( entityName ); } } else { //TODO: only for implicit columns? //FIXME NamingStrategy for (Ejb3JoinColumn column : joinColumns) { String mappedByProperty = mappings.getFromMappedBy( collValue.getOwnerEntityName(), column.getPropertyName() ); Table ownerTable = collValue.getOwner().getTable(); column.setMappedBy( collValue.getOwner().getEntityName(), mappings.getLogicalTableName( ownerTable ), mappedByProperty );// String header = ( mappedByProperty == null ) ? mappings.getLogicalTableName( ownerTable ) : mappedByProperty;// column.setDefaultColumnHeader( header ); } if ( StringHelper.isEmpty( associationTableBinder.getName() ) ) { //default value associationTableBinder.setDefaultName( collValue.getOwner().getEntityName(), mappings.getLogicalTableName( collValue.getOwner().getTable() ), collectionEntity != null ? collectionEntity.getEntityName() : null, collectionEntity != null ? mappings.getLogicalTableName( collectionEntity.getTable() ) : null, joinColumns[0].getPropertyName() ); } collValue.setCollectionTable( associationTableBinder.bind() ); } bindFilters( isCollectionOfEntities ); bindCollectionSecondPass( collValue, collectionEntity, joinColumns, cascadeDeleteEnabled, property, mappings ); ManyToOne element = null; if ( isCollectionOfEntities ) { element = new ManyToOne( collValue.getCollectionTable() ); collValue.setElement( element ); element.setReferencedEntityName( collType.getName() ); //element.setFetchMode( fetchMode ); //element.setLazy( fetchMode != FetchMode.JOIN ); //make the second join non lazy element.setFetchMode( FetchMode.JOIN ); element.setLazy( false ); element.setIgnoreNotFound( ignoreNotFound ); if ( StringHelper.isNotEmpty( hqlOrderBy ) ) { collValue.setManyToManyOrdering( buildOrderByClauseFromHql( hqlOrderBy, collectionEntity, collValue.getRole() ) ); } ForeignKey fk = property != null ? property.getAnnotation( ForeignKey.class ) : null; String fkName = fk != null ? fk.inverseName() : ""; if ( !BinderHelper.isDefault( fkName ) ) element.setForeignKeyName( fkName ); } else if ( anyAnn != null ) { //@ManyToAny //Make sure that collTyp is never used during the @ManyToAny branch: it will be set to void.class PropertyData inferredData = new PropertyInferredData( property, "unsupported", mappings.getReflectionManager() ); //override the table for (Ejb3Column column : inverseJoinColumns) { column.setTable( collValue.getCollectionTable() ); } Any any = BinderHelper.buildAnyValue( anyAnn.metaDef(), inverseJoinColumns, anyAnn.metaColumn(), inferredData, cascadeDeleteEnabled, Nullability.NO_CONSTRAINT, propertyHolder, new EntityBinder(), true, mappings ); collValue.setElement( any ); } else { XClass elementClass; AnnotatedClassType classType;// Map<String, javax.persistence.Column[]> columnOverrides = PropertyHolderBuilder.buildColumnOverride(// property, StringHelper.qualify( collValue.getRole(), "element" )// ); //FIXME the "element" is lost PropertyHolder holder = null; if ( BinderHelper.PRIMITIVE_NAMES.contains( collType.getName() ) ) { classType = AnnotatedClassType.NONE; elementClass = null; } else { elementClass = collType; classType = mappings.getClassType( elementClass ); holder = PropertyHolderBuilder.buildPropertyHolder( collValue, collValue.getRole(), // + ".element", elementClass, property, parentPropertyHolder, mappings ); //force in case of attribute override boolean attributeOverride = property.isAnnotationPresent( AttributeOverride.class ) || property.isAnnotationPresent( AttributeOverrides.class ); if ( isEmbedded || attributeOverride ) { classType = AnnotatedClassType.EMBEDDABLE; } } if ( AnnotatedClassType.EMBEDDABLE.equals( classType ) ) { EntityBinder entityBinder = new EntityBinder(); PersistentClass owner = collValue.getOwner(); boolean isPropertyAnnotated; //FIXME support @Access for collection of elements //String accessType = access != null ? access.value() : null; if ( owner.getIdentifierProperty() != null ) { isPropertyAnnotated = owner.getIdentifierProperty().getPropertyAccessorName().equals( "property" ); } else if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) { Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next(); isPropertyAnnotated = prop.getPropertyAccessorName().equals( "property" ); } else { throw new AssertionFailure( "Unable to guess collection property accessor name" ); } //boolean propertyAccess = embeddable == null || AccessType.PROPERTY.equals( embeddable.access() ); PropertyData inferredData = new PropertyPreloadedData( "property", "element", elementClass ); //TODO be smart with isNullable Component component = AnnotationBinder.fillComponent( holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true, entityBinder, false, false, true, mappings ); collValue.setElement( component ); if ( StringHelper.isNotEmpty( hqlOrderBy ) ) { String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName(); String orderBy = buildOrderByClauseFromHql( hqlOrderBy, component, path ); if ( orderBy != null ) { collValue.setOrderBy( orderBy ); } } } else { SimpleValueBinder elementBinder = new SimpleValueBinder(); elementBinder.setMappings( mappings ); elementBinder.setReturnedClassName( collType.getName() ); if ( elementColumns == null || elementColumns.length == 0 ) { elementColumns = new Ejb3Column[1]; Ejb3Column column = new Ejb3Column(); column.setImplicit( false ); //not following the spec but more clean column.setNullable( true ); column.setLength( Ejb3Column.DEFAULT_COLUMN_LENGTH ); column.setLogicalColumnName( Collection.DEFAULT_ELEMENT_COLUMN_NAME ); //TODO create an EMPTY_JOINS collection column.setJoins( new HashMap<String, Join>() ); column.setMappings( mappings ); column.bind(); elementColumns[0] = column; } //override the table for (Ejb3Column column : elementColumns) { column.setTable( collValue.getCollectionTable() ); } elementBinder.setColumns( elementColumns ); elementBinder.setType( property, elementClass ); collValue.setElement( elementBinder.make() ); } } checkFilterConditions( collValue ); //FIXME: do optional = false if ( isCollectionOfEntities ) { bindManytoManyInverseFk( collectionEntity, inverseJoinColumns, element, unique, mappings ); } } private static void checkFilterConditions(Collection collValue) { //for now it can't happen, but sometime soon... if ( ( collValue.getFilterMap().size() != 0 || StringHelper.isNotEmpty( collValue.getWhere() ) ) && collValue.getFetchMode() == FetchMode.JOIN && !( collValue.getElement() instanceof SimpleValue ) && //SimpleValue (CollectionOfElements) are always SELECT but it does not matter collValue.getElement().getFetchMode() != FetchMode.JOIN ) { throw new MappingException( "@ManyToMany or @CollectionOfElements defining filter or where without join fetching " + "not valid within collection using join fetching[" + collValue.getRole() + "]" ); } } private static void bindCollectionSecondPass( Collection collValue, PersistentClass collectionEntity, Ejb3JoinColumn[] joinColumns, boolean cascadeDeleteEnabled, XProperty property, ExtendedMappings mappings ) { BinderHelper.createSyntheticPropertyReference( joinColumns, collValue.getOwner(), collectionEntity, collValue, false, mappings ); SimpleValue key = buildCollectionKey( collValue, joinColumns, cascadeDeleteEnabled, property, mappings ); TableBinder.bindFk( collValue.getOwner(), collectionEntity, joinColumns, key, false, mappings ); } public void setCascadeDeleteEnabled(boolean onDeleteCascade) { this.cascadeDeleteEnabled = onDeleteCascade; } private String safeCollectionRole() { if ( propertyHolder != null ) { return propertyHolder.getEntityName() + "." + propertyName; } else { return ""; } } /** * bind the inverse FK of a ManyToMany * If we are in a mappedBy case, read the columns from the associated * colletion element * Otherwise delegates to the usual algorithm */ public static void bindManytoManyInverseFk( PersistentClass referencedEntity, Ejb3JoinColumn[] columns, SimpleValue value, boolean unique, ExtendedMappings mappings ) { final String mappedBy = columns[0].getMappedBy(); if ( StringHelper.isNotEmpty( mappedBy ) ) { final Property property = referencedEntity.getRecursiveProperty( mappedBy ); Iterator mappedByColumns; if ( property.getValue() instanceof Collection ) { mappedByColumns = ( (Collection) property.getValue() ).getKey().getColumnIterator(); } else { //find the appropriate reference key, can be in a join Iterator joinsIt = referencedEntity.getJoinIterator(); KeyValue key = null; while ( joinsIt.hasNext() ) { Join join = (Join) joinsIt.next(); if ( join.containsProperty( property ) ) { key = join.getKey(); break; } } if ( key == null ) key = property.getPersistentClass().getIdentifier(); mappedByColumns = key.getColumnIterator(); } while ( mappedByColumns.hasNext() ) { Column column = (Column) mappedByColumns.next(); columns[0].linkValueUsingAColumnCopy( column, value ); } String referencedPropertyName = mappings.getPropertyReferencedAssociation( "inverse__" + referencedEntity.getEntityName(), mappedBy ); if ( referencedPropertyName != null ) { //TODO always a many to one? ( (ManyToOne) value ).setReferencedPropertyName( referencedPropertyName ); mappings.addUniquePropertyReference( referencedEntity.getEntityName(), referencedPropertyName ); } value.createForeignKey(); } else { BinderHelper.createSyntheticPropertyReference( columns, referencedEntity, null, value, true, mappings ); TableBinder.bindFk( referencedEntity, null, columns, value, unique, mappings ); } } public void setFkJoinColumns(Ejb3JoinColumn[] ejb3JoinColumns) { this.fkJoinColumns = ejb3JoinColumns; } public void setExplicitAssociationTable(boolean explicitAssocTable) { this.isExplicitAssociationTable = explicitAssocTable; } public void setElementColumns(Ejb3Column[] elementColumns) { this.elementColumns = elementColumns; } public void setEmbedded(boolean annotationPresent) { this.isEmbedded = annotationPresent; } public void setProperty(XProperty property) { this.property = property; } public void setIgnoreNotFound(boolean ignoreNotFound) { this.ignoreNotFound = ignoreNotFound; } public void setMapKeyColumns(Ejb3Column[] mapKeyColumns) { this.mapKeyColumns = mapKeyColumns; } public void setMapKeyManyToManyColumns(Ejb3JoinColumn[] mapJoinColumns) { this.mapKeyManyToManyColumns = mapJoinColumns; } public void setLocalGenerators(HashMap<String, IdGenerator> localGenerators) { this.localGenerators = localGenerators; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -